worsoft-frontend-codegen-local-mcp 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -3
- package/assets/templates/master_child_jump/api.tpl +2 -2
- package/assets/templates/master_child_jump/form.tpl +24 -13
- package/assets/templates/master_child_jump/index.tpl +30 -3
- package/assets/templates/master_child_jump/options.tpl +28 -6
- package/assets/templates/single_table_dialog/form.tpl +15 -2
- package/assets/templates/single_table_dialog/index.tpl +31 -3
- package/assets/templates/single_table_dialog/options.tpl +28 -6
- package/assets/templates/single_table_jump/form.tpl +15 -1
- package/assets/templates/single_table_jump/index.tpl +30 -3
- package/assets/templates/single_table_jump/options.tpl +28 -6
- package/mcp_server.js +626 -92
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@ This MCP generates Worsoft frontend files from a local Markdown design document.
|
|
|
24
24
|
- `mainField` when `style=master_child_jump`: required
|
|
25
25
|
- `childField` when `style=master_child_jump`: required
|
|
26
26
|
- `relationType` when `style=master_child_jump`: optional
|
|
27
|
+
- `children` when `style=master_child_jump`: optional array of direct child relations; when provided it overrides the legacy single-child fields
|
|
27
28
|
|
|
28
29
|
## Recommended MCP Arguments
|
|
29
30
|
|
|
@@ -57,6 +58,33 @@ Master-child:
|
|
|
57
58
|
}
|
|
58
59
|
```
|
|
59
60
|
|
|
61
|
+
Multi direct children on one main form:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"tableName": "iwm_sys_trade_level",
|
|
66
|
+
"style": "master_child_jump",
|
|
67
|
+
"children": [
|
|
68
|
+
{
|
|
69
|
+
"childTableName": "iwm_sys_trade_level_standard",
|
|
70
|
+
"mainField": "id",
|
|
71
|
+
"childField": "trade_level_id",
|
|
72
|
+
"relationType": "1:N"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"childTableName": "iwm_sys_trade_level_competency",
|
|
76
|
+
"mainField": "id",
|
|
77
|
+
"childField": "trade_level_id",
|
|
78
|
+
"relationType": "1:N"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"designFile": "plugins/sql/SQL 璁捐璇存槑.md",
|
|
82
|
+
"frontendPath": "E:/own-worker-platform/trunk/worsoft-ui",
|
|
83
|
+
"moduleName": "admin/test",
|
|
84
|
+
"writeToDisk": false
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
60
88
|
## Smoke Test
|
|
61
89
|
|
|
62
90
|
PowerShell:
|
|
@@ -65,6 +93,7 @@ PowerShell:
|
|
|
65
93
|
powershell -ExecutionPolicy Bypass -File plugins/worsoft-codegen-local/smoke_test_mcp.ps1 -Scenario single
|
|
66
94
|
powershell -ExecutionPolicy Bypass -File plugins/worsoft-codegen-local/smoke_test_mcp.ps1 -Scenario master
|
|
67
95
|
powershell -ExecutionPolicy Bypass -File plugins/worsoft-codegen-local/smoke_test_mcp.ps1 -Scenario child
|
|
96
|
+
powershell -ExecutionPolicy Bypass -File plugins/worsoft-codegen-local/smoke_test_mcp.ps1 -Scenario multi
|
|
68
97
|
powershell -ExecutionPolicy Bypass -File plugins/worsoft-codegen-local/smoke_test_mcp.ps1 -Scenario missing_relation
|
|
69
98
|
```
|
|
70
99
|
|
|
@@ -74,6 +103,7 @@ Node:
|
|
|
74
103
|
node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario single
|
|
75
104
|
node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario master
|
|
76
105
|
node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario child
|
|
106
|
+
node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario multi
|
|
77
107
|
node plugins/worsoft-codegen-local/smoke_test_mcp.js --scenario missing_relation
|
|
78
108
|
```
|
|
79
109
|
|
|
@@ -95,9 +125,8 @@ For `master_child_jump`, MCP does not infer relations from the design file anymo
|
|
|
95
125
|
|
|
96
126
|
The caller must provide:
|
|
97
127
|
|
|
98
|
-
- `
|
|
99
|
-
- `mainField`
|
|
100
|
-
- `childField`
|
|
128
|
+
- either `children[]`
|
|
129
|
+
- or the legacy single-child fields: `childTableName`, `mainField`, `childField`
|
|
101
130
|
|
|
102
131
|
If these fields are missing, MCP returns `relation_input_required`.
|
|
103
132
|
|
|
@@ -40,10 +40,10 @@ export function putObj(obj?: object) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export function delChildObj(ids?: object) {
|
|
43
|
+
export function delChildObj(ids?: object, childTableName?: string) {
|
|
44
44
|
return request({
|
|
45
45
|
url: '/{{API_PATH}}/child',
|
|
46
46
|
method: 'delete',
|
|
47
|
-
data: ids,
|
|
47
|
+
data: childTableName ? { ids, childTableName } : ids,
|
|
48
48
|
});
|
|
49
49
|
}
|
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
{{FORM_FIELDS}}
|
|
10
10
|
</el-row>
|
|
11
11
|
<el-row :gutter="24">
|
|
12
|
-
|
|
13
|
-
{{CHILD_TABLE_COLUMNS}}
|
|
14
|
-
</sc-form-table>
|
|
12
|
+
{{CHILD_SECTIONS}}
|
|
15
13
|
</el-row>
|
|
16
14
|
</el-form>
|
|
17
15
|
<div class="dialog-footer" style="text-align: right; margin-top: 18px;">
|
|
@@ -26,7 +24,10 @@
|
|
|
26
24
|
import mittBus from '/@/utils/mitt';
|
|
27
25
|
import { useMessage } from '/@/hooks/message';
|
|
28
26
|
import { getObj, addObj, putObj, delChildObj } from '/@/api/{{API_MODULE_PATH}}';
|
|
29
|
-
{
|
|
27
|
+
import { useDict } from '/@/hooks/dict';
|
|
28
|
+
import { allDictTypes, childFieldGroups, dataMasterEntity } from './options';
|
|
29
|
+
|
|
30
|
+
const dictRefs = useDict(...allDictTypes);
|
|
30
31
|
|
|
31
32
|
const scFormTable = defineAsyncComponent(() => import('/@/components/FormTable/index.vue'));
|
|
32
33
|
const route = useRoute();
|
|
@@ -36,14 +37,24 @@ const dataFormRef = ref();
|
|
|
36
37
|
const loading = ref(false);
|
|
37
38
|
const detail = ref(false);
|
|
38
39
|
|
|
40
|
+
const masterFields = dataMasterEntity;
|
|
41
|
+
|
|
42
|
+
const getMasterFieldMeta = (prop: string) => masterFields[prop];
|
|
43
|
+
const isMasterFieldVisible = (prop: string) => {
|
|
44
|
+
const config = getMasterFieldMeta(prop);
|
|
45
|
+
return Boolean(config) && !config.alwaysHide && config.show !== false;
|
|
46
|
+
};
|
|
47
|
+
const getChildFieldMeta = (groupName: string, prop: string) => childFieldGroups[groupName]?.[prop];
|
|
48
|
+
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
49
|
+
const inputPlaceholder = (label: string) => `请输入${label}`;
|
|
50
|
+
const selectPlaceholder = (label: string) => `请选择${label}`;
|
|
51
|
+
|
|
39
52
|
const form = reactive({
|
|
40
53
|
{{FORM_DEFAULTS}}
|
|
41
|
-
|
|
54
|
+
{{CHILD_FORM_LIST_DEFAULTS}}
|
|
42
55
|
});
|
|
43
56
|
|
|
44
|
-
|
|
45
|
-
{{CHILD_TEMP_DEFAULTS}}
|
|
46
|
-
});
|
|
57
|
+
{{CHILD_TEMP_DECLARATIONS}}
|
|
47
58
|
|
|
48
59
|
const dataRules = ref({
|
|
49
60
|
{{FORM_RULES}}
|
|
@@ -64,11 +75,11 @@ const get{{CLASS_NAME}}Data = async (id: string) => {
|
|
|
64
75
|
const resetFormState = () => {
|
|
65
76
|
Object.assign(form, {
|
|
66
77
|
{{FORM_DEFAULTS}}
|
|
67
|
-
|
|
78
|
+
{{CHILD_FORM_LIST_DEFAULTS}}
|
|
68
79
|
});
|
|
69
80
|
nextTick(() => {
|
|
70
81
|
dataFormRef.value?.resetFields();
|
|
71
|
-
|
|
82
|
+
{{CHILD_RESET_LISTS}}
|
|
72
83
|
});
|
|
73
84
|
};
|
|
74
85
|
|
|
@@ -113,10 +124,10 @@ const onSubmit = async () => {
|
|
|
113
124
|
}
|
|
114
125
|
};
|
|
115
126
|
|
|
116
|
-
const deleteChild = async (obj:
|
|
117
|
-
if (obj
|
|
127
|
+
const deleteChild = async (obj: Record<string, any>, childPkAttr: string, childTableName?: string) => {
|
|
128
|
+
if (obj[childPkAttr]) {
|
|
118
129
|
try {
|
|
119
|
-
await delChildObj([obj
|
|
130
|
+
await delChildObj([obj[childPkAttr]], childTableName);
|
|
120
131
|
useMessage().success('删除成功');
|
|
121
132
|
} catch (err: any) {
|
|
122
133
|
useMessage().error(err.msg || '删除失败');
|
|
@@ -21,7 +21,19 @@
|
|
|
21
21
|
>
|
|
22
22
|
<el-table-column type="selection" width="40" align="center" />
|
|
23
23
|
<el-table-column type="index" label="#" width="40" />
|
|
24
|
-
|
|
24
|
+
<el-table-column
|
|
25
|
+
v-for="column in visibleTableColumns"
|
|
26
|
+
:key="column.prop"
|
|
27
|
+
:prop="column.prop"
|
|
28
|
+
:label="column.label"
|
|
29
|
+
:width="column.width"
|
|
30
|
+
show-overflow-tooltip
|
|
31
|
+
>
|
|
32
|
+
<template #default="scope">
|
|
33
|
+
<dict-tag v-if="column.dictType" :options="getDictOptions(column.dictType)" :value="scope.row[column.prop]" />
|
|
34
|
+
<span v-else>{{ scope.row[column.prop] }}</span>
|
|
35
|
+
</template>
|
|
36
|
+
</el-table-column>
|
|
25
37
|
<el-table-column label="操作" width="220">
|
|
26
38
|
<template #default="scope">
|
|
27
39
|
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(scope.row.{{PK_ATTR}})">查看</el-button>
|
|
@@ -42,11 +54,13 @@
|
|
|
42
54
|
import { BasicTableProps, useTable } from '/@/hooks/table';
|
|
43
55
|
import { fetchList, delObjs } from '/@/api/{{API_MODULE_PATH}}';
|
|
44
56
|
import { useMessage, useMessageBox } from '/@/hooks/message';
|
|
45
|
-
{
|
|
57
|
+
import { useDict } from '/@/hooks/dict';
|
|
58
|
+
import { allDictTypes, dataMasterEntity } from './options';
|
|
59
|
+
|
|
60
|
+
const dictRefs = useDict(...allDictTypes);
|
|
46
61
|
const router = useRouter();
|
|
47
62
|
|
|
48
63
|
const excelUploadRef = ref();
|
|
49
|
-
const queryRef = ref();
|
|
50
64
|
const showSearch = ref(true);
|
|
51
65
|
const selectObjs = ref([]) as any;
|
|
52
66
|
const multiple = ref(true);
|
|
@@ -56,6 +70,19 @@ const state: BasicTableProps = reactive<BasicTableProps>({
|
|
|
56
70
|
pageList: fetchList,
|
|
57
71
|
});
|
|
58
72
|
|
|
73
|
+
const visibleTableColumns = computed(() =>
|
|
74
|
+
Object.entries(dataMasterEntity)
|
|
75
|
+
.filter(([, config]) => !config.alwaysHide && config.show !== false)
|
|
76
|
+
.map(([prop, config]) => ({
|
|
77
|
+
prop,
|
|
78
|
+
label: config.label,
|
|
79
|
+
width: config.width,
|
|
80
|
+
dictType: config.dictType || '',
|
|
81
|
+
}))
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
85
|
+
|
|
59
86
|
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state);
|
|
60
87
|
|
|
61
88
|
const getFormPath = () => '/{{VIEW_MODULE_PATH}}/form';
|
|
@@ -1,10 +1,32 @@
|
|
|
1
|
+
{{DICT_REGISTRY_IMPORT_BLOCK}}
|
|
2
|
+
import { createCrudSchema } from '/@/utils/crudSchema';
|
|
3
|
+
import type { CrudSchemaDefinition } from '/@/utils/crudSchema';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
6
|
+
* {{TABLE_NAME}} 页面字段声明。
|
|
7
|
+
* 这里只维护字段清单,不手写派生配置。
|
|
3
8
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
const definition: CrudSchemaDefinition = {
|
|
10
|
+
// 主表字段
|
|
11
|
+
master: [
|
|
12
|
+
{{MASTER_OPTION_FIELDS}}
|
|
13
|
+
],
|
|
14
|
+
// 子表字段,key 对应 form.vue 中的列表字段名
|
|
15
|
+
children: {
|
|
16
|
+
{{CHILD_OPTION_GROUPS}}
|
|
17
|
+
},
|
|
6
18
|
};
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
// 统一派生页面所需配置,避免在 options 文件里重复手写
|
|
21
|
+
const schema = createCrudSchema(definition);
|
|
22
|
+
|
|
23
|
+
// 主表字段配置:列表页、主表表单共用
|
|
24
|
+
export const dataMasterEntity = schema.master;
|
|
25
|
+
// 子表字段配置:主子表 form 页使用
|
|
26
|
+
export const childFieldGroups = schema.children;
|
|
27
|
+
// 主表字典筛选配置
|
|
28
|
+
export const filterTypes = schema.filterTypes;
|
|
29
|
+
// 子表字典筛选配置
|
|
30
|
+
export const childFilterTypes = schema.childFilterTypes;
|
|
31
|
+
// 当前功能涉及的全部字典编码
|
|
32
|
+
export const allDictTypes = schema.allDictTypes;
|
|
@@ -17,14 +17,27 @@
|
|
|
17
17
|
<script setup lang="ts" name="{{CLASS_NAME}}Dialog">
|
|
18
18
|
import { useMessage } from '/@/hooks/message';
|
|
19
19
|
import { getObj, addObj, putObj } from '/@/api/{{API_MODULE_PATH}}';
|
|
20
|
-
{
|
|
20
|
+
import { useDict } from '/@/hooks/dict';
|
|
21
|
+
import { allDictTypes, dataMasterEntity } from './options';
|
|
21
22
|
|
|
23
|
+
const dictRefs = useDict(...allDictTypes);
|
|
22
24
|
const emit = defineEmits(['refresh']);
|
|
23
25
|
|
|
24
26
|
const dataFormRef = ref();
|
|
25
27
|
const visible = ref(false);
|
|
26
28
|
const loading = ref(false);
|
|
27
29
|
|
|
30
|
+
const masterFields = dataMasterEntity;
|
|
31
|
+
|
|
32
|
+
const getMasterFieldMeta = (prop: string) => masterFields[prop];
|
|
33
|
+
const isMasterFieldVisible = (prop: string) => {
|
|
34
|
+
const config = getMasterFieldMeta(prop);
|
|
35
|
+
return Boolean(config) && !config.alwaysHide && config.show !== false;
|
|
36
|
+
};
|
|
37
|
+
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
38
|
+
const inputPlaceholder = (label: string) => `请输入${label}`;
|
|
39
|
+
const selectPlaceholder = (label: string) => `请选择${label}`;
|
|
40
|
+
|
|
28
41
|
const form = reactive({
|
|
29
42
|
{{FORM_DEFAULTS}}
|
|
30
43
|
});
|
|
@@ -88,4 +101,4 @@ const onSubmit = async () => {
|
|
|
88
101
|
defineExpose({
|
|
89
102
|
openDialog,
|
|
90
103
|
});
|
|
91
|
-
</script>
|
|
104
|
+
</script>
|
|
@@ -21,7 +21,19 @@
|
|
|
21
21
|
>
|
|
22
22
|
<el-table-column type="selection" width="40" align="center" />
|
|
23
23
|
<el-table-column type="index" label="#" width="40" />
|
|
24
|
-
|
|
24
|
+
<el-table-column
|
|
25
|
+
v-for="column in visibleTableColumns"
|
|
26
|
+
:key="column.prop"
|
|
27
|
+
:prop="column.prop"
|
|
28
|
+
:label="column.label"
|
|
29
|
+
:width="column.width"
|
|
30
|
+
show-overflow-tooltip
|
|
31
|
+
>
|
|
32
|
+
<template #default="scope">
|
|
33
|
+
<dict-tag v-if="column.dictType" :options="getDictOptions(column.dictType)" :value="scope.row[column.prop]" />
|
|
34
|
+
<span v-else>{{ scope.row[column.prop] }}</span>
|
|
35
|
+
</template>
|
|
36
|
+
</el-table-column>
|
|
25
37
|
<el-table-column label="操作" width="180">
|
|
26
38
|
<template #default="scope">
|
|
27
39
|
<el-button icon="edit-pen" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_edit'" @click="formDialogRef.openDialog(scope.row.{{PK_ATTR}})">编辑</el-button>
|
|
@@ -42,7 +54,10 @@
|
|
|
42
54
|
import { BasicTableProps, useTable } from '/@/hooks/table';
|
|
43
55
|
import { fetchList, delObjs } from '/@/api/{{API_MODULE_PATH}}';
|
|
44
56
|
import { useMessage, useMessageBox } from '/@/hooks/message';
|
|
45
|
-
{
|
|
57
|
+
import { useDict } from '/@/hooks/dict';
|
|
58
|
+
import { allDictTypes, dataMasterEntity } from './options';
|
|
59
|
+
|
|
60
|
+
const dictRefs = useDict(...allDictTypes);
|
|
46
61
|
|
|
47
62
|
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
|
48
63
|
|
|
@@ -57,6 +72,19 @@ const state: BasicTableProps = reactive<BasicTableProps>({
|
|
|
57
72
|
pageList: fetchList,
|
|
58
73
|
});
|
|
59
74
|
|
|
75
|
+
const visibleTableColumns = computed(() =>
|
|
76
|
+
Object.entries(dataMasterEntity)
|
|
77
|
+
.filter(([, config]) => !config.alwaysHide && config.show !== false)
|
|
78
|
+
.map(([prop, config]) => ({
|
|
79
|
+
prop,
|
|
80
|
+
label: config.label,
|
|
81
|
+
width: config.width,
|
|
82
|
+
dictType: config.dictType || '',
|
|
83
|
+
}))
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
87
|
+
|
|
60
88
|
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state);
|
|
61
89
|
|
|
62
90
|
const exportExcel = () => {
|
|
@@ -83,4 +111,4 @@ const handleDelete = async (ids: string[]) => {
|
|
|
83
111
|
useMessage().error(err.msg || '删除失败');
|
|
84
112
|
}
|
|
85
113
|
};
|
|
86
|
-
</script>
|
|
114
|
+
</script>
|
|
@@ -1,10 +1,32 @@
|
|
|
1
|
+
{{DICT_REGISTRY_IMPORT_BLOCK}}
|
|
2
|
+
import { createCrudSchema } from '/@/utils/crudSchema';
|
|
3
|
+
import type { CrudSchemaDefinition } from '/@/utils/crudSchema';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
6
|
+
* {{TABLE_NAME}} 页面字段声明。
|
|
7
|
+
* 这里只维护字段清单,不手写派生配置。
|
|
3
8
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
const definition: CrudSchemaDefinition = {
|
|
10
|
+
// 主表字段
|
|
11
|
+
master: [
|
|
12
|
+
{{MASTER_OPTION_FIELDS}}
|
|
13
|
+
],
|
|
14
|
+
// 子表字段,key 对应 form.vue 中的列表字段名
|
|
15
|
+
children: {
|
|
16
|
+
{{CHILD_OPTION_GROUPS}}
|
|
17
|
+
},
|
|
6
18
|
};
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
// 统一派生页面所需配置,避免在 options 文件里重复手写
|
|
21
|
+
const schema = createCrudSchema(definition);
|
|
22
|
+
|
|
23
|
+
// 主表字段配置:列表页、主表表单共用
|
|
24
|
+
export const dataMasterEntity = schema.master;
|
|
25
|
+
// 子表字段配置:主子表 form 页使用
|
|
26
|
+
export const childFieldGroups = schema.children;
|
|
27
|
+
// 主表字典筛选配置
|
|
28
|
+
export const filterTypes = schema.filterTypes;
|
|
29
|
+
// 子表字典筛选配置
|
|
30
|
+
export const childFilterTypes = schema.childFilterTypes;
|
|
31
|
+
// 当前功能涉及的全部字典编码
|
|
32
|
+
export const allDictTypes = schema.allDictTypes;
|
|
@@ -21,7 +21,10 @@
|
|
|
21
21
|
import mittBus from '/@/utils/mitt';
|
|
22
22
|
import { useMessage } from '/@/hooks/message';
|
|
23
23
|
import { getObj, addObj, putObj } from '/@/api/{{API_MODULE_PATH}}';
|
|
24
|
-
{
|
|
24
|
+
import { useDict } from '/@/hooks/dict';
|
|
25
|
+
import { allDictTypes, dataMasterEntity } from './options';
|
|
26
|
+
|
|
27
|
+
const dictRefs = useDict(...allDictTypes);
|
|
25
28
|
const route = useRoute();
|
|
26
29
|
const router = useRouter();
|
|
27
30
|
|
|
@@ -29,6 +32,17 @@ const dataFormRef = ref();
|
|
|
29
32
|
const loading = ref(false);
|
|
30
33
|
const detail = ref(false);
|
|
31
34
|
|
|
35
|
+
const masterFields = dataMasterEntity;
|
|
36
|
+
|
|
37
|
+
const getMasterFieldMeta = (prop: string) => masterFields[prop];
|
|
38
|
+
const isMasterFieldVisible = (prop: string) => {
|
|
39
|
+
const config = getMasterFieldMeta(prop);
|
|
40
|
+
return Boolean(config) && !config.alwaysHide && config.show !== false;
|
|
41
|
+
};
|
|
42
|
+
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
43
|
+
const inputPlaceholder = (label: string) => `请输入${label}`;
|
|
44
|
+
const selectPlaceholder = (label: string) => `请选择${label}`;
|
|
45
|
+
|
|
32
46
|
const form = reactive({
|
|
33
47
|
{{FORM_DEFAULTS}}
|
|
34
48
|
});
|
|
@@ -21,7 +21,19 @@
|
|
|
21
21
|
>
|
|
22
22
|
<el-table-column type="selection" width="40" align="center" />
|
|
23
23
|
<el-table-column type="index" label="#" width="40" />
|
|
24
|
-
|
|
24
|
+
<el-table-column
|
|
25
|
+
v-for="column in visibleTableColumns"
|
|
26
|
+
:key="column.prop"
|
|
27
|
+
:prop="column.prop"
|
|
28
|
+
:label="column.label"
|
|
29
|
+
:width="column.width"
|
|
30
|
+
show-overflow-tooltip
|
|
31
|
+
>
|
|
32
|
+
<template #default="scope">
|
|
33
|
+
<dict-tag v-if="column.dictType" :options="getDictOptions(column.dictType)" :value="scope.row[column.prop]" />
|
|
34
|
+
<span v-else>{{ scope.row[column.prop] }}</span>
|
|
35
|
+
</template>
|
|
36
|
+
</el-table-column>
|
|
25
37
|
<el-table-column label="操作" width="220">
|
|
26
38
|
<template #default="scope">
|
|
27
39
|
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(scope.row.{{PK_ATTR}})">查看</el-button>
|
|
@@ -42,11 +54,13 @@
|
|
|
42
54
|
import { BasicTableProps, useTable } from '/@/hooks/table';
|
|
43
55
|
import { fetchList, delObjs } from '/@/api/{{API_MODULE_PATH}}';
|
|
44
56
|
import { useMessage, useMessageBox } from '/@/hooks/message';
|
|
45
|
-
{
|
|
57
|
+
import { useDict } from '/@/hooks/dict';
|
|
58
|
+
import { allDictTypes, dataMasterEntity } from './options';
|
|
59
|
+
|
|
60
|
+
const dictRefs = useDict(...allDictTypes);
|
|
46
61
|
const router = useRouter();
|
|
47
62
|
|
|
48
63
|
const excelUploadRef = ref();
|
|
49
|
-
const queryRef = ref();
|
|
50
64
|
const showSearch = ref(true);
|
|
51
65
|
const selectObjs = ref([]) as any;
|
|
52
66
|
const multiple = ref(true);
|
|
@@ -56,6 +70,19 @@ const state: BasicTableProps = reactive<BasicTableProps>({
|
|
|
56
70
|
pageList: fetchList,
|
|
57
71
|
});
|
|
58
72
|
|
|
73
|
+
const visibleTableColumns = computed(() =>
|
|
74
|
+
Object.entries(dataMasterEntity)
|
|
75
|
+
.filter(([, config]) => !config.alwaysHide && config.show !== false)
|
|
76
|
+
.map(([prop, config]) => ({
|
|
77
|
+
prop,
|
|
78
|
+
label: config.label,
|
|
79
|
+
width: config.width,
|
|
80
|
+
dictType: config.dictType || '',
|
|
81
|
+
}))
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const getDictOptions = (dictType?: string) => (dictType ? dictRefs[dictType]?.value || [] : []);
|
|
85
|
+
|
|
59
86
|
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state);
|
|
60
87
|
|
|
61
88
|
const getFormPath = () => '/{{VIEW_MODULE_PATH}}/form';
|
|
@@ -1,10 +1,32 @@
|
|
|
1
|
+
{{DICT_REGISTRY_IMPORT_BLOCK}}
|
|
2
|
+
import { createCrudSchema } from '/@/utils/crudSchema';
|
|
3
|
+
import type { CrudSchemaDefinition } from '/@/utils/crudSchema';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
6
|
+
* {{TABLE_NAME}} 页面字段声明。
|
|
7
|
+
* 这里只维护字段清单,不手写派生配置。
|
|
3
8
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
const definition: CrudSchemaDefinition = {
|
|
10
|
+
// 主表字段
|
|
11
|
+
master: [
|
|
12
|
+
{{MASTER_OPTION_FIELDS}}
|
|
13
|
+
],
|
|
14
|
+
// 子表字段,key 对应 form.vue 中的列表字段名
|
|
15
|
+
children: {
|
|
16
|
+
{{CHILD_OPTION_GROUPS}}
|
|
17
|
+
},
|
|
6
18
|
};
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
// 统一派生页面所需配置,避免在 options 文件里重复手写
|
|
21
|
+
const schema = createCrudSchema(definition);
|
|
22
|
+
|
|
23
|
+
// 主表字段配置:列表页、主表表单共用
|
|
24
|
+
export const dataMasterEntity = schema.master;
|
|
25
|
+
// 子表字段配置:主子表 form 页使用
|
|
26
|
+
export const childFieldGroups = schema.children;
|
|
27
|
+
// 主表字典筛选配置
|
|
28
|
+
export const filterTypes = schema.filterTypes;
|
|
29
|
+
// 子表字典筛选配置
|
|
30
|
+
export const childFilterTypes = schema.childFilterTypes;
|
|
31
|
+
// 当前功能涉及的全部字典编码
|
|
32
|
+
export const allDictTypes = schema.allDictTypes;
|