worsoft-frontend-codegen-local-mcp 0.1.64 → 0.1.66
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/api.tpl +5 -46
- package/assets/templates/master_child_jump/form.tpl +8 -0
- package/assets/templates/master_child_jump/index.tpl +10 -0
- package/assets/templates/master_child_jump/menu.sql.tpl +5 -1
- package/assets/templates/single_table_dialog/api.tpl +5 -46
- 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/api.tpl +5 -46
- package/assets/templates/single_table_jump/form.tpl +7 -0
- package/assets/templates/single_table_jump/index.tpl +8 -0
- package/assets/templates/single_table_jump/menu.sql.tpl +5 -1
- package/mcp_server.js +237 -66
- package/package.json +1 -1
|
@@ -1,48 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
import
|
|
1
|
+
// 通用 CRUD 接口工厂
|
|
2
|
+
import { createCrudApi } from '/@/api/common/crudFactory';
|
|
3
|
+
{{API_REQUEST_IMPORT}}
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
export
|
|
6
|
-
return request({
|
|
7
|
-
url: '/{{API_PATH}}/page',
|
|
8
|
-
method: 'get',
|
|
9
|
-
params: query,
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 新增数据
|
|
14
|
-
export function addObj(obj?: object) {
|
|
15
|
-
return request({
|
|
16
|
-
url: '/{{API_PATH}}/save',
|
|
17
|
-
method: 'post',
|
|
18
|
-
data: obj,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 查询详情数据
|
|
23
|
-
export function getObj(obj?: object) {
|
|
24
|
-
return request({
|
|
25
|
-
url: '/{{API_PATH}}/getById',
|
|
26
|
-
method: 'get',
|
|
27
|
-
params: obj,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 删除数据
|
|
32
|
-
export function delObjs(ids?: object) {
|
|
33
|
-
return request({
|
|
34
|
-
url: '/{{API_PATH}}/removeByIds',
|
|
35
|
-
method: 'post',
|
|
36
|
-
data: ids,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 更新数据
|
|
41
|
-
export function putObj(obj?: object) {
|
|
42
|
-
return request({
|
|
43
|
-
url: '/{{API_PATH}}/updateById',
|
|
44
|
-
method: 'post',
|
|
45
|
-
data: obj,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
5
|
+
// {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新接口
|
|
6
|
+
export const { fetchList, addObj, getObj, delObjs, putObj } = createCrudApi('/{{API_PATH}}');
|
|
48
7
|
{{EXTRA_API_FUNCTIONS}}
|
|
@@ -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>
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
6
6
|
values ({{MENU_BASE_ID}}, '-1', '/{{MENU_ROUTE_PATH}}/index', '', '0', 'icon-bangzhushouji', '0', null, '8', null, '{{TABLE_COMMENT}}管理', 1);
|
|
7
7
|
|
|
8
|
+
-- Form route SQL for jump-based pages. Hidden from sidebar, used by list page add/edit/view navigation.
|
|
9
|
+
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, visible, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
10
|
+
values ({{MENU_BASE_ID_PLUS_6}}, {{MENU_BASE_ID}}, '/{{MENU_ROUTE_PATH}}/form', '', '0', 'icon-biaodan', '0', '0', null, '9', null, '{{TABLE_COMMENT}}表单', 1);
|
|
11
|
+
|
|
8
12
|
insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
9
13
|
values ({{MENU_BASE_ID_PLUS_1}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_view', '1', null, '1', '0', null, '0', null, '{{TABLE_COMMENT}}查看', 1);
|
|
10
14
|
|
|
@@ -18,4 +22,4 @@ insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del
|
|
|
18
22
|
values ({{MENU_BASE_ID_PLUS_4}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_del', '1', null, '1', '0', null, '3', null, '{{TABLE_COMMENT}}删除', 1);
|
|
19
23
|
|
|
20
24
|
insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
21
|
-
values ({{MENU_BASE_ID_PLUS_5}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_export', '1', null, '1', '0', null, '4', null, '导入导出', 1);
|
|
25
|
+
values ({{MENU_BASE_ID_PLUS_5}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_export', '1', null, '1', '0', null, '4', null, '导入导出', 1);
|
|
@@ -1,50 +1,9 @@
|
|
|
1
|
-
//
|
|
2
|
-
import
|
|
1
|
+
// 通用 CRUD 接口工厂
|
|
2
|
+
import { createCrudApi } from '/@/api/common/crudFactory';
|
|
3
|
+
{{API_REQUEST_IMPORT}}
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
export
|
|
6
|
-
return request({
|
|
7
|
-
url: '/{{API_PATH}}/page',
|
|
8
|
-
method: 'get',
|
|
9
|
-
params: query,
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 新增数据
|
|
14
|
-
export function addObj(obj?: object) {
|
|
15
|
-
return request({
|
|
16
|
-
url: '/{{API_PATH}}',
|
|
17
|
-
method: 'post',
|
|
18
|
-
data: obj,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 查询详情数据
|
|
23
|
-
export function getObj(obj?: object) {
|
|
24
|
-
return request({
|
|
25
|
-
url: '/{{API_PATH}}/details',
|
|
26
|
-
method: 'get',
|
|
27
|
-
params: obj,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 删除数据
|
|
32
|
-
export function delObjs(ids?: object) {
|
|
33
|
-
return request({
|
|
34
|
-
url: '/{{API_PATH}}',
|
|
35
|
-
method: 'delete',
|
|
36
|
-
data: ids,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 更新数据
|
|
41
|
-
export function putObj(obj?: object) {
|
|
42
|
-
return request({
|
|
43
|
-
url: '/{{API_PATH}}',
|
|
44
|
-
method: 'put',
|
|
45
|
-
data: obj,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
5
|
+
// {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新接口
|
|
6
|
+
export const { fetchList, addObj, getObj, delObjs, putObj } = createCrudApi('/{{API_PATH}}');
|
|
48
7
|
|
|
49
8
|
{{DICT_API_FUNCTIONS}}
|
|
50
9
|
{{EXTRA_API_FUNCTIONS}}
|
|
@@ -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,48 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
import
|
|
1
|
+
// 通用 CRUD 接口工厂
|
|
2
|
+
import { createCrudApi } from '/@/api/common/crudFactory';
|
|
3
|
+
{{API_REQUEST_IMPORT}}
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
export
|
|
6
|
-
return request({
|
|
7
|
-
url: '/{{API_PATH}}/page',
|
|
8
|
-
method: 'get',
|
|
9
|
-
params: query,
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 新增数据
|
|
14
|
-
export function addObj(obj?: object) {
|
|
15
|
-
return request({
|
|
16
|
-
url: '/{{API_PATH}}',
|
|
17
|
-
method: 'post',
|
|
18
|
-
data: obj,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 查询详情数据
|
|
23
|
-
export function getObj(obj?: object) {
|
|
24
|
-
return request({
|
|
25
|
-
url: '/{{API_PATH}}/details',
|
|
26
|
-
method: 'get',
|
|
27
|
-
params: obj,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 删除数据
|
|
32
|
-
export function delObjs(ids?: object) {
|
|
33
|
-
return request({
|
|
34
|
-
url: '/{{API_PATH}}',
|
|
35
|
-
method: 'delete',
|
|
36
|
-
data: ids,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 更新数据
|
|
41
|
-
export function putObj(obj?: object) {
|
|
42
|
-
return request({
|
|
43
|
-
url: '/{{API_PATH}}',
|
|
44
|
-
method: 'put',
|
|
45
|
-
data: obj,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
5
|
+
// {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新接口
|
|
6
|
+
export const { fetchList, addObj, getObj, delObjs, putObj } = createCrudApi('/{{API_PATH}}');
|
|
48
7
|
{{EXTRA_API_FUNCTIONS}}
|
|
@@ -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>
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
6
6
|
values ({{MENU_BASE_ID}}, '-1', '/{{MENU_ROUTE_PATH}}/index', '', '0', 'icon-bangzhushouji', '0', null, '8', null, '{{TABLE_COMMENT}}管理', 1);
|
|
7
7
|
|
|
8
|
+
-- Form route SQL for jump-based pages. Hidden from sidebar, used by list page add/edit/view navigation.
|
|
9
|
+
insert into sys_menu (menu_id, parent_id, path, permission, menu_type, icon, visible, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
10
|
+
values ({{MENU_BASE_ID_PLUS_6}}, {{MENU_BASE_ID}}, '/{{MENU_ROUTE_PATH}}/form', '', '0', 'icon-biaodan', '0', '0', null, '9', null, '{{TABLE_COMMENT}}表单', 1);
|
|
11
|
+
|
|
8
12
|
insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
9
13
|
values ({{MENU_BASE_ID_PLUS_1}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_view', '1', null, '1', '0', null, '0', null, '{{TABLE_COMMENT}}查看', 1);
|
|
10
14
|
|
|
@@ -18,4 +22,4 @@ insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del
|
|
|
18
22
|
values ({{MENU_BASE_ID_PLUS_4}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_del', '1', null, '1', '0', null, '3', null, '{{TABLE_COMMENT}}删除', 1);
|
|
19
23
|
|
|
20
24
|
insert into sys_menu (menu_id, parent_id, permission, menu_type, path, icon, del_flag, create_time, sort_order, update_time, name, tenant_id)
|
|
21
|
-
values ({{MENU_BASE_ID_PLUS_5}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_export', '1', null, '1', '0', null, '4', null, '导入导出', 1);
|
|
25
|
+
values ({{MENU_BASE_ID_PLUS_5}}, {{MENU_BASE_ID}}, '{{PERMISSION_PREFIX}}_export', '1', null, '1', '0', null, '4', null, '导入导出', 1);
|
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.66';
|
|
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');
|
|
@@ -146,10 +146,65 @@ export function createCrudSchema(
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
return buildSchema(masterOrDefinition as Record<string, FieldMeta>, children);
|
|
149
|
-
}
|
|
150
|
-
`;
|
|
151
|
-
|
|
152
|
-
const
|
|
149
|
+
}
|
|
150
|
+
`;
|
|
151
|
+
|
|
152
|
+
const DEFAULT_CRUD_FACTORY_TEMPLATE = `import request from '/@/utils/request';
|
|
153
|
+
|
|
154
|
+
export interface CrudApiPathOverrides {
|
|
155
|
+
page?: string;
|
|
156
|
+
save?: string;
|
|
157
|
+
detail?: string;
|
|
158
|
+
remove?: string;
|
|
159
|
+
update?: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const joinApiPath = (baseUrl: string, suffix: string) => {
|
|
163
|
+
const normalizedBase = String(baseUrl || '').replace(/\\/+$/, '');
|
|
164
|
+
const normalizedSuffix = String(suffix || '').replace(/^\\/+/, '');
|
|
165
|
+
return normalizedSuffix ? \`\${normalizedBase}/\${normalizedSuffix}\` : normalizedBase;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// 生成标准业务功能 CRUD 接口:分页、新增、详情、删除、更新。
|
|
169
|
+
export const createCrudApi = (baseUrl: string, overrides: CrudApiPathOverrides = {}) => ({
|
|
170
|
+
fetchList: (query?: object) =>
|
|
171
|
+
request({
|
|
172
|
+
url: overrides.page || joinApiPath(baseUrl, 'page'),
|
|
173
|
+
method: 'get',
|
|
174
|
+
params: query,
|
|
175
|
+
}),
|
|
176
|
+
|
|
177
|
+
addObj: (obj?: object) =>
|
|
178
|
+
request({
|
|
179
|
+
url: overrides.save || joinApiPath(baseUrl, 'save'),
|
|
180
|
+
method: 'post',
|
|
181
|
+
data: obj,
|
|
182
|
+
}),
|
|
183
|
+
|
|
184
|
+
getObj: (obj?: object) =>
|
|
185
|
+
request({
|
|
186
|
+
url: overrides.detail || joinApiPath(baseUrl, 'getById'),
|
|
187
|
+
method: 'get',
|
|
188
|
+
params: obj,
|
|
189
|
+
}),
|
|
190
|
+
|
|
191
|
+
delObjs: (ids?: object) =>
|
|
192
|
+
request({
|
|
193
|
+
url: overrides.remove || joinApiPath(baseUrl, 'removeByIds'),
|
|
194
|
+
method: 'post',
|
|
195
|
+
data: ids,
|
|
196
|
+
}),
|
|
197
|
+
|
|
198
|
+
putObj: (obj?: object) =>
|
|
199
|
+
request({
|
|
200
|
+
url: overrides.update || joinApiPath(baseUrl, 'updateById'),
|
|
201
|
+
method: 'post',
|
|
202
|
+
data: obj,
|
|
203
|
+
}),
|
|
204
|
+
});
|
|
205
|
+
`;
|
|
206
|
+
|
|
207
|
+
const TOOL_SCHEMA = {
|
|
153
208
|
type: 'object',
|
|
154
209
|
properties: {
|
|
155
210
|
featureTitle: { type: 'string', description: 'Feature title from pre-parsed structured metadata.' },
|
|
@@ -340,11 +395,11 @@ const TOOL_SCHEMA = {
|
|
|
340
395
|
},
|
|
341
396
|
writeToDisk: { type: 'boolean', default: true, description: 'Whether to write generated files.' },
|
|
342
397
|
overwrite: { type: 'boolean', default: true, description: 'Whether to overwrite existing files. If false, existing files are skipped.' },
|
|
343
|
-
writeSupportFiles: {
|
|
344
|
-
type: 'boolean',
|
|
345
|
-
default: true,
|
|
346
|
-
description: 'Whether to write project support files such as src/enums/dict-registry.ts
|
|
347
|
-
},
|
|
398
|
+
writeSupportFiles: {
|
|
399
|
+
type: 'boolean',
|
|
400
|
+
default: true,
|
|
401
|
+
description: 'Whether to write project support files such as src/enums/dict-registry.ts, src/utils/crudSchema.ts and src/api/common/crudFactory.ts.'
|
|
402
|
+
},
|
|
348
403
|
mergeI18nZh: {
|
|
349
404
|
type: 'boolean',
|
|
350
405
|
default: true,
|
|
@@ -835,7 +890,7 @@ function prepareDictRegistry(frontendPath, dictTypes) {
|
|
|
835
890
|
};
|
|
836
891
|
}
|
|
837
892
|
|
|
838
|
-
function ensureCrudSchemaSupportFile(frontendPath) {
|
|
893
|
+
function ensureCrudSchemaSupportFile(frontendPath) {
|
|
839
894
|
const schemaPath = path.join(frontendPath, 'src', 'utils', 'crudSchema.ts');
|
|
840
895
|
const exists = fs.existsSync(schemaPath);
|
|
841
896
|
const currentContent = exists ? readUtf8File(schemaPath) : '';
|
|
@@ -852,12 +907,27 @@ function ensureCrudSchemaSupportFile(frontendPath) {
|
|
|
852
907
|
exists,
|
|
853
908
|
isCompatible: hasCoreShape && supportsLabelKey,
|
|
854
909
|
needsWrite: !exists || shouldUpgradeLegacy,
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
function
|
|
859
|
-
|
|
860
|
-
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function ensureCrudFactorySupportFile(frontendPath) {
|
|
914
|
+
const factoryPath = path.join(frontendPath, 'src', 'api', 'common', 'crudFactory.ts');
|
|
915
|
+
const exists = fs.existsSync(factoryPath);
|
|
916
|
+
const currentContent = exists ? readUtf8File(factoryPath) : '';
|
|
917
|
+
const isCompatible = !exists || currentContent.includes('export const createCrudApi');
|
|
918
|
+
|
|
919
|
+
return {
|
|
920
|
+
path: factoryPath,
|
|
921
|
+
content: DEFAULT_CRUD_FACTORY_TEMPLATE,
|
|
922
|
+
exists,
|
|
923
|
+
isCompatible,
|
|
924
|
+
needsWrite: !exists,
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function ensureDirectory(filePath) {
|
|
929
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
930
|
+
}
|
|
861
931
|
|
|
862
932
|
function writeSupportFile(filePath, content) {
|
|
863
933
|
ensureDirectory(filePath);
|
|
@@ -880,30 +950,52 @@ function prepareSharedSupport(frontendPath, dictTypes, writeSupportFiles) {
|
|
|
880
950
|
const normalizedDictTypes = [...new Set((dictTypes || []).filter(Boolean))];
|
|
881
951
|
const dictRegistry = writeSupportFiles ? prepareDictRegistry(frontendPath, normalizedDictTypes) : buildVirtualDictRegistry(normalizedDictTypes);
|
|
882
952
|
const crudSchemaPath = path.join(frontendPath, 'src', 'utils', 'crudSchema.ts');
|
|
883
|
-
const crudSchema = writeSupportFiles
|
|
884
|
-
? ensureCrudSchemaSupportFile(frontendPath)
|
|
885
|
-
: {
|
|
886
|
-
path: crudSchemaPath,
|
|
953
|
+
const crudSchema = writeSupportFiles
|
|
954
|
+
? ensureCrudSchemaSupportFile(frontendPath)
|
|
955
|
+
: {
|
|
956
|
+
path: crudSchemaPath,
|
|
887
957
|
content: DEFAULT_CRUD_SCHEMA_TEMPLATE,
|
|
888
958
|
exists: fs.existsSync(crudSchemaPath),
|
|
889
959
|
isCompatible: true,
|
|
890
|
-
needsWrite: false,
|
|
891
|
-
writeEnabled: false,
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
960
|
+
needsWrite: false,
|
|
961
|
+
writeEnabled: false,
|
|
962
|
+
};
|
|
963
|
+
const crudFactoryPath = path.join(frontendPath, 'src', 'api', 'common', 'crudFactory.ts');
|
|
964
|
+
const crudFactory = writeSupportFiles
|
|
965
|
+
? ensureCrudFactorySupportFile(frontendPath)
|
|
966
|
+
: {
|
|
967
|
+
path: crudFactoryPath,
|
|
968
|
+
content: DEFAULT_CRUD_FACTORY_TEMPLATE,
|
|
969
|
+
exists: fs.existsSync(crudFactoryPath),
|
|
970
|
+
isCompatible: true,
|
|
971
|
+
needsWrite: false,
|
|
972
|
+
writeEnabled: false,
|
|
973
|
+
};
|
|
974
|
+
return {
|
|
975
|
+
dictRegistry,
|
|
976
|
+
crudSchema,
|
|
977
|
+
crudFactory,
|
|
978
|
+
writeEnabled: Boolean(writeSupportFiles),
|
|
979
|
+
};
|
|
980
|
+
}
|
|
899
981
|
|
|
900
982
|
function maybeWriteSharedSupport(sharedSupport, writeToDisk) {
|
|
901
983
|
if (!writeToDisk || !sharedSupport.writeEnabled) return;
|
|
902
984
|
|
|
903
|
-
if (sharedSupport.crudSchema.needsWrite) {
|
|
904
|
-
writeSupportFile(sharedSupport.crudSchema.path, sharedSupport.crudSchema.content);
|
|
905
|
-
}
|
|
906
|
-
|
|
985
|
+
if (sharedSupport.crudSchema.needsWrite) {
|
|
986
|
+
writeSupportFile(sharedSupport.crudSchema.path, sharedSupport.crudSchema.content);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
if (sharedSupport.crudFactory.needsWrite) {
|
|
990
|
+
if (!sharedSupport.crudFactory.isCompatible) {
|
|
991
|
+
throw new Error(
|
|
992
|
+
'Detected an existing src/api/common/crudFactory.ts that MCP could not merge safely. ' +
|
|
993
|
+
'Please align the createCrudApi export manually before enabling writeSupportFiles.'
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
writeSupportFile(sharedSupport.crudFactory.path, sharedSupport.crudFactory.content);
|
|
997
|
+
}
|
|
998
|
+
|
|
907
999
|
if (sharedSupport.dictRegistry.needsWrite) {
|
|
908
1000
|
if (!sharedSupport.dictRegistry.isCompatible) {
|
|
909
1001
|
throw new Error(
|
|
@@ -918,11 +1010,11 @@ function maybeWriteSharedSupport(sharedSupport, writeToDisk) {
|
|
|
918
1010
|
function buildSupportNote(sharedSupport, localeZhSupport) {
|
|
919
1011
|
const notes = [];
|
|
920
1012
|
|
|
921
|
-
if (!sharedSupport.writeEnabled) {
|
|
922
|
-
notes.push(
|
|
923
|
-
'Shared support file writing is disabled. Generated code still references src/utils/crudSchema.ts and may reference src/enums/dict-registry.ts, so those helpers must already exist in the target project.'
|
|
924
|
-
);
|
|
925
|
-
}
|
|
1013
|
+
if (!sharedSupport.writeEnabled) {
|
|
1014
|
+
notes.push(
|
|
1015
|
+
'Shared support file writing is disabled. Generated code still references src/utils/crudSchema.ts, src/api/common/crudFactory.ts and may reference src/enums/dict-registry.ts, so those helpers must already exist in the target project.'
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
926
1018
|
|
|
927
1019
|
if (sharedSupport.crudSchema.exists && !sharedSupport.crudSchema.isCompatible) {
|
|
928
1020
|
notes.push(
|
|
@@ -931,6 +1023,13 @@ function buildSupportNote(sharedSupport, localeZhSupport) {
|
|
|
931
1023
|
);
|
|
932
1024
|
}
|
|
933
1025
|
|
|
1026
|
+
if (sharedSupport.crudFactory.exists && !sharedSupport.crudFactory.isCompatible) {
|
|
1027
|
+
notes.push(
|
|
1028
|
+
'Detected an existing src/api/common/crudFactory.ts that does not export createCrudApi. ' +
|
|
1029
|
+
'MCP preserved the existing file and did not overwrite it. Generated API modules now depend on that file being manually aligned.'
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
934
1033
|
if (sharedSupport.dictRegistry.exists && !sharedSupport.dictRegistry.isCompatible) {
|
|
935
1034
|
notes.push(
|
|
936
1035
|
'Detected an existing src/enums/dict-registry.ts that MCP could not merge safely. ' +
|
|
@@ -1956,10 +2055,12 @@ function renderChildSection(childModel, childCount) {
|
|
|
1956
2055
|
|
|
1957
2056
|
return [
|
|
1958
2057
|
' <el-col :span="24" class="mb20">',
|
|
2058
|
+
` <!-- 子表区域:${sanitizeHtmlComment(childModel.comment || childModel.tableName)} -->`,
|
|
1959
2059
|
` <div class="mb10" style="font-weight: 600;">{{ childSectionTitle('${childModel.listName}') }}</div>`,
|
|
2060
|
+
' <!-- 子表编辑表格:支持新增行、删除行和行内字段编辑 -->',
|
|
1960
2061
|
` <sc-form-table v-model="form.${childModel.listName}" :addTemplate="childTemp${childModel.className}" @delete="(obj) => ${deleteExpression}" :placeholder="t('common.noData')">`,
|
|
1961
2062
|
childModel.visibleFields.map((field) => renderChildTableColumn(field, childModel.listName)).join('\n'),
|
|
1962
|
-
' </sc-form-table>',
|
|
2063
|
+
' </sc-form-table>',
|
|
1963
2064
|
' </el-col>',
|
|
1964
2065
|
].join('\n');
|
|
1965
2066
|
}
|
|
@@ -2504,14 +2605,18 @@ function renderMultiLevelFormVue(model, moduleModel) {
|
|
|
2504
2605
|
].join('\n');
|
|
2505
2606
|
const rules = renderFormRulesV2(moduleModel.visibleFields);
|
|
2506
2607
|
return `<template>
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2608
|
+
<!-- 表单弹窗:新增或编辑${sanitizeHtmlComment(moduleModel.comment || moduleModel.tableName)}数据 -->
|
|
2609
|
+
<el-dialog v-model="visible" :title="form.${moduleModel.pk.attrName} ? t('common.editBtn') : t('common.addBtn')" :close-on-click-modal="false" draggable>
|
|
2610
|
+
<!-- 弹窗表单:按 PRD 表单显隐和顺序渲染字段 -->
|
|
2611
|
+
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="100px" v-loading="loading">
|
|
2612
|
+
<!-- 字典字段区:字段级注释由 MCP 根据字段名称生成 -->
|
|
2613
|
+
<el-row :gutter="24">
|
|
2614
|
+
${moduleModel.visibleFields.map(renderMultiLevelFormField).join('\n')}
|
|
2615
|
+
</el-row>
|
|
2616
|
+
</el-form>
|
|
2617
|
+
<!-- 弹窗底部操作按钮:取消和确认提交 -->
|
|
2618
|
+
<template #footer>
|
|
2619
|
+
<span class="dialog-footer">
|
|
2515
2620
|
<el-button @click="visible = false">{{ t('common.cancelButtonText') }}</el-button>
|
|
2516
2621
|
<el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
|
|
2517
2622
|
</span>
|
|
@@ -2642,11 +2747,14 @@ ${moduleModel.visibleFields.map(renderMultiLevelFormField).join('\n')}
|
|
|
2642
2747
|
function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
|
|
2643
2748
|
return [
|
|
2644
2749
|
` <div class="multi-level-slot" v-if="${levelVarName}">`,
|
|
2750
|
+
' <!-- 多层字典页签:切换当前层级下的字典模块 -->',
|
|
2645
2751
|
' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
|
|
2646
2752
|
` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
|
|
2647
2753
|
' </el-tabs>',
|
|
2754
|
+
' <!-- 多层字典列表面板:承载当前层级的工具栏和表格 -->',
|
|
2648
2755
|
' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
|
|
2649
2756
|
' <div class="layout-padding-auto layout-padding-view flex h-full flex-col">',
|
|
2757
|
+
' <!-- 当前层级工具栏:搜索、新增和重置 -->',
|
|
2650
2758
|
` <SchemaListToolbar`,
|
|
2651
2759
|
` v-bind="getPanelToolbarProps(${activeModuleVarName}.key)"`,
|
|
2652
2760
|
` @update:keyword="handlePanelKeywordChange(${activeModuleVarName}.key, $event)"`,
|
|
@@ -2654,16 +2762,22 @@ function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeMo
|
|
|
2654
2762
|
` @query="handlePanelQuery(${activeModuleVarName}.key)"`,
|
|
2655
2763
|
` @reset="handlePanelReset(${activeModuleVarName}.key)"`,
|
|
2656
2764
|
` />`,
|
|
2765
|
+
' <!-- 当前层级表格:展示字典数据、分页和行操作 -->',
|
|
2657
2766
|
` <SchemaListTable`,
|
|
2658
2767
|
` v-bind="getPanelTableProps(${activeModuleVarName}.key)"`,
|
|
2659
2768
|
` @row-current-change="handlePanelCurrentChange(${activeModuleVarName}.key, $event.row)"`,
|
|
2660
2769
|
` @current-change="handleCurrentPageChange(${activeModuleVarName}.key, $event.current)"`,
|
|
2661
2770
|
` @size-change="handlePageSizeChange(${activeModuleVarName}.key, $event.size)"`,
|
|
2662
2771
|
` >`,
|
|
2772
|
+
' <!-- 行操作按钮:编辑、删除、启用、禁用 -->',
|
|
2663
2773
|
` <template #actions="{ row }">`,
|
|
2774
|
+
' <!-- 编辑当前字典数据 -->',
|
|
2664
2775
|
` <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>`,
|
|
2776
|
+
' <!-- 删除当前字典数据 -->',
|
|
2665
2777
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
|
|
2778
|
+
' <!-- 启用当前字典数据 -->',
|
|
2666
2779
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'enable', row)" icon="circle-check" text type="primary" @click="handleEnable(${activeModuleVarName}.key, row)">闁告凹鍨抽弫?/el-button>`,
|
|
2780
|
+
' <!-- 禁用当前字典数据 -->',
|
|
2667
2781
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'disable', row)" icon="remove" text type="primary" @click="handleDisable(${activeModuleVarName}.key, row)">缂佸倷鑳堕弫?/el-button>`,
|
|
2668
2782
|
` </template>`,
|
|
2669
2783
|
` </SchemaListTable>`,
|
|
@@ -2676,14 +2790,18 @@ function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeMo
|
|
|
2676
2790
|
function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
|
|
2677
2791
|
return [
|
|
2678
2792
|
` <div class="multi-level-slot" v-if="${levelVarName}">`,
|
|
2793
|
+
' <!-- 多层字典页签:切换当前层级下的字典模块 -->',
|
|
2679
2794
|
' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
|
|
2680
2795
|
` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
|
|
2681
2796
|
' </el-tabs>',
|
|
2797
|
+
' <!-- 多层字典列表面板:承载当前层级的新增按钮、表格和分页 -->',
|
|
2682
2798
|
' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
|
|
2683
2799
|
' <div class="layout-padding-auto layout-padding-view flex h-full flex-col">',
|
|
2800
|
+
' <!-- 当前层级新增按钮:受父级状态约束控制 -->',
|
|
2684
2801
|
' <div class="mb8" style="width: 100%">',
|
|
2685
2802
|
` <el-button icon="folder-add" type="primary" class="ml10" :disabled="isAddDisabled(${activeModuleVarName}.key)" @click="openCreate(${activeModuleVarName}.key)">{{ t('common.addBtn') }}</el-button>`,
|
|
2686
2803
|
' </div>',
|
|
2804
|
+
' <!-- 当前层级表格:展示字典数据并处理行选中联动 -->',
|
|
2687
2805
|
' <el-table',
|
|
2688
2806
|
` :data="moduleStateMap[${activeModuleVarName}.key].dataList"`,
|
|
2689
2807
|
` v-loading="moduleStateMap[${activeModuleVarName}.key].loading"`,
|
|
@@ -2692,7 +2810,9 @@ function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleV
|
|
|
2692
2810
|
' highlight-current-row',
|
|
2693
2811
|
` @current-change="handlePanelCurrentChange(${activeModuleVarName}.key, $event)"`,
|
|
2694
2812
|
' >',
|
|
2813
|
+
' <!-- 序号列 -->',
|
|
2695
2814
|
` <el-table-column type="index" :label="t('common.serial')" width="60" />`,
|
|
2815
|
+
' <!-- 字典业务字段列 -->',
|
|
2696
2816
|
` <el-table-column`,
|
|
2697
2817
|
` v-for="column in getListFields(${activeModuleVarName}.key)"`,
|
|
2698
2818
|
' :key="column.key"',
|
|
@@ -2706,15 +2826,21 @@ function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleV
|
|
|
2706
2826
|
' <span v-else>{{ scope.row[column.key] }}</span>',
|
|
2707
2827
|
' </template>',
|
|
2708
2828
|
' </el-table-column>',
|
|
2829
|
+
' <!-- 行操作按钮:编辑、删除、启用、禁用 -->',
|
|
2709
2830
|
` <el-table-column :label="t('common.action')" width="260">`,
|
|
2710
2831
|
' <template #default="{ row }">',
|
|
2832
|
+
' <!-- 编辑当前字典数据 -->',
|
|
2711
2833
|
` <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>`,
|
|
2834
|
+
' <!-- 删除当前字典数据 -->',
|
|
2712
2835
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
|
|
2836
|
+
' <!-- 启用当前字典数据 -->',
|
|
2713
2837
|
` <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>`,
|
|
2838
|
+
' <!-- 禁用当前字典数据 -->',
|
|
2714
2839
|
` <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>`,
|
|
2715
2840
|
' </template>',
|
|
2716
2841
|
' </el-table-column>',
|
|
2717
2842
|
' </el-table>',
|
|
2843
|
+
' <!-- 当前层级分页组件 -->',
|
|
2718
2844
|
' <div class="mt-2.5 flex shrink-0 justify-end">',
|
|
2719
2845
|
' <pagination',
|
|
2720
2846
|
` :current-page="moduleStateMap[${activeModuleVarName}.key].currentPage"`,
|
|
@@ -2766,24 +2892,31 @@ function renderMultiLevelIndexVue(model) {
|
|
|
2766
2892
|
|
|
2767
2893
|
return `<!-- 功能名称:${sanitizeHtmlComment(model.featureTitle)} -->
|
|
2768
2894
|
<template>
|
|
2895
|
+
<!-- 页面布局:${sanitizeHtmlComment(model.featureTitle)}多层字典列表页 -->
|
|
2769
2896
|
<div class="layout-padding">
|
|
2897
|
+
<!-- 多层字典主布局:左侧一级字典,右侧二级和三级字典联动 -->
|
|
2770
2898
|
<div class="multi-level-dict-layout">
|
|
2771
|
-
|
|
2899
|
+
<!-- 一级字典区域 -->
|
|
2900
|
+
<div class="multi-level-left">
|
|
2772
2901
|
${renderMultiLevelSchemaListSlot('level1Config', 'activeLevel1Key', 'activeLevel1Module')}
|
|
2773
|
-
</div>
|
|
2774
|
-
|
|
2775
|
-
|
|
2902
|
+
</div>
|
|
2903
|
+
<!-- 二级和三级字典区域 -->
|
|
2904
|
+
<div class="multi-level-right">
|
|
2905
|
+
<!-- 二级字典区域 -->
|
|
2906
|
+
<div class="multi-level-right-top">
|
|
2776
2907
|
${level2 ? renderMultiLevelSchemaListSlot('level2Config', 'activeLevel2Key', 'activeLevel2Module') : ''}
|
|
2777
|
-
</div>
|
|
2778
|
-
|
|
2908
|
+
</div>
|
|
2909
|
+
<!-- 三级字典区域 -->
|
|
2910
|
+
<div v-if="level3Config" class="multi-level-right-bottom">
|
|
2779
2911
|
${level3 ? renderMultiLevelSchemaListSlot('level3Config', 'activeLevel3Key', 'activeLevel3Module') : ''}
|
|
2780
|
-
</div>
|
|
2781
|
-
</div>
|
|
2782
|
-
</div>
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
</
|
|
2912
|
+
</div>
|
|
2913
|
+
</div>
|
|
2914
|
+
</div>
|
|
2915
|
+
|
|
2916
|
+
<!-- 多层字典表单弹窗:按模块异步挂载 -->
|
|
2917
|
+
${formComponents}
|
|
2918
|
+
</div>
|
|
2919
|
+
</template>
|
|
2787
2920
|
|
|
2788
2921
|
<script setup lang="ts" name="system${model.className}">
|
|
2789
2922
|
// 通用消息与确认弹窗
|
|
@@ -3055,11 +3188,15 @@ function renderSingleTableDialogActions(model, permissionPrefix) {
|
|
|
3055
3188
|
const pkAttr = model.pk.attrName;
|
|
3056
3189
|
const isDictWithStatus = model.pageType === 'dict' && model.statusField;
|
|
3057
3190
|
const lines = [
|
|
3191
|
+
` <!-- 编辑${sanitizeHtmlComment(model.featureTitle)} -->`,
|
|
3058
3192
|
` <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>`,
|
|
3193
|
+
` <!-- 删除${sanitizeHtmlComment(model.featureTitle)} -->`,
|
|
3059
3194
|
` <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>`,
|
|
3060
3195
|
];
|
|
3061
3196
|
if (isDictWithStatus) {
|
|
3197
|
+
lines.push(` <!-- 启用${sanitizeHtmlComment(model.featureTitle)} -->`);
|
|
3062
3198
|
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>`);
|
|
3199
|
+
lines.push(` <!-- 禁用${sanitizeHtmlComment(model.featureTitle)} -->`);
|
|
3063
3200
|
lines.push(` <el-button v-if="showDictAction('disable', row)" icon="remove" text type="primary" @click="handleDisable(row.${pkAttr})">{{ t('common.actions.disable') }}</el-button>`);
|
|
3064
3201
|
}
|
|
3065
3202
|
return lines.join('\n');
|
|
@@ -3188,6 +3325,38 @@ function renderExtraApiFunctions(model) {
|
|
|
3188
3325
|
.join('\n');
|
|
3189
3326
|
}
|
|
3190
3327
|
|
|
3328
|
+
function renderApiRequestImport(model) {
|
|
3329
|
+
const hasExtraApis = Array.isArray(model.extraApis) && model.extraApis.length > 0;
|
|
3330
|
+
const hasDictStatusApis = model.pageType === 'dict' && !!model.statusField;
|
|
3331
|
+
return hasExtraApis || hasDictStatusApis ? "import request from '/@/utils/request';" : '';
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3334
|
+
function renderExtraApiFunctionsV2(model) {
|
|
3335
|
+
if (!Array.isArray(model.extraApis) || !model.extraApis.length) return '';
|
|
3336
|
+
return model.extraApis
|
|
3337
|
+
.map((api) => {
|
|
3338
|
+
const requestField = api.requestType === 'data' ? 'data' : 'params';
|
|
3339
|
+
const lines = ['', `// 额外接口:${sanitizeComment(api.description)}`];
|
|
3340
|
+
if (api.usedBy) {
|
|
3341
|
+
lines.push(`// 使用场景:${sanitizeComment(api.usedBy)}`);
|
|
3342
|
+
}
|
|
3343
|
+
if (api.source) {
|
|
3344
|
+
lines.push(`// 来源说明:${sanitizeComment(api.source)}`);
|
|
3345
|
+
}
|
|
3346
|
+
lines.push(
|
|
3347
|
+
`export function ${api.functionName}(payload?: any) {`,
|
|
3348
|
+
' return request({',
|
|
3349
|
+
` url: '${api.url}',`,
|
|
3350
|
+
` method: '${api.method}',`,
|
|
3351
|
+
` ${requestField}: payload,`,
|
|
3352
|
+
' });',
|
|
3353
|
+
'}'
|
|
3354
|
+
);
|
|
3355
|
+
return lines.join('\n');
|
|
3356
|
+
})
|
|
3357
|
+
.join('\n');
|
|
3358
|
+
}
|
|
3359
|
+
|
|
3191
3360
|
function buildReplacements(model, sharedSupport) {
|
|
3192
3361
|
const menuBaseId = Date.now();
|
|
3193
3362
|
const apiModulePath = model.targetApiModule || `${model.moduleName}/${model.functionName}`;
|
|
@@ -3218,16 +3387,18 @@ function buildReplacements(model, sharedSupport) {
|
|
|
3218
3387
|
BUSINESS_STATUS_IMPORTS: renderBusinessStatusImports(model),
|
|
3219
3388
|
BUSINESS_EDIT_IF: hasBusinessBillStateEditControl(model) ? ' v-if="showEditAction(row)"' : '',
|
|
3220
3389
|
BUSINESS_STATUS_HELPERS: renderBusinessStatusHelpers(model),
|
|
3221
|
-
|
|
3390
|
+
API_REQUEST_IMPORT: renderApiRequestImport(model),
|
|
3391
|
+
EXTRA_API_FUNCTIONS: renderExtraApiFunctionsV2(model),
|
|
3222
3392
|
CUSTOM_QUERY_FIELDS_EXPR: model.pageType === 'dict' ? '[]' : 'queryableDictOptions.value',
|
|
3223
3393
|
SHOW_RIGHT_TOOLS: model.pageType === 'dict' ? 'false' : 'true',
|
|
3224
3394
|
MENU_BASE_ID: menuBaseId,
|
|
3225
3395
|
MENU_BASE_ID_PLUS_1: menuBaseId + 1,
|
|
3226
3396
|
MENU_BASE_ID_PLUS_2: menuBaseId + 2,
|
|
3227
|
-
MENU_BASE_ID_PLUS_3: menuBaseId + 3,
|
|
3228
|
-
MENU_BASE_ID_PLUS_4: menuBaseId + 4,
|
|
3229
|
-
MENU_BASE_ID_PLUS_5: menuBaseId + 5,
|
|
3230
|
-
|
|
3397
|
+
MENU_BASE_ID_PLUS_3: menuBaseId + 3,
|
|
3398
|
+
MENU_BASE_ID_PLUS_4: menuBaseId + 4,
|
|
3399
|
+
MENU_BASE_ID_PLUS_5: menuBaseId + 5,
|
|
3400
|
+
MENU_BASE_ID_PLUS_6: menuBaseId + 6,
|
|
3401
|
+
GENERATED_AT: new Date().toISOString(),
|
|
3231
3402
|
FORM_FIELDS: model.visibleFields.map(renderFormFieldV2).join('\n'),
|
|
3232
3403
|
TABLE_COLUMNS: model.gridFields.map((field) => renderTableColumn(field, dictRegistryRefs)).join('\n'),
|
|
3233
3404
|
FORM_DEFAULTS: renderFormDefaults(model),
|
package/package.json
CHANGED