Commit 6d179320c9e1bf2f1c27b75608a8a524a10d8ea7

Authored by 芋道源码
Committed by Gitee
2 parents 436eb29d 2d0f9899

!1328 【功能新增】代码生成: vue3_vben5_antd schema 主子表 erp 模板

Merge pull request !1328 from puhui999/master-jdk17
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
... ... @@ -154,15 +154,15 @@ public class CodegenEngine {
154 154 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("api/api.ts"),
155 155 vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
156 156 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑
157   - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
  157 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
158 158 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑
159   - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
  159 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
160 160 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑
161   - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
  161 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
162 162 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑
163   - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}List.vue"))
  163 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
164 164 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑
165   - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}List.vue"))
  165 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
166 166 .build();
167 167  
168 168 @Resource
... ... @@ -451,6 +451,8 @@ public class CodegenEngine {
451 451 filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName());
452 452 filePath = StrUtil.replace(filePath, "${subSimpleClassName}",
453 453 ((List<String>) bindingMap.get("subSimpleClassNames")).get(subIndex));
  454 + filePath = StrUtil.replace(filePath, "${subSimpleClassName_strikeCase}",
  455 + ((List<String>) bindingMap.get("subSimpleClassName_strikeCases")).get(subIndex));
454 456 }
455 457 return filePath;
456 458 }
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/api/api.ts.vm
... ... @@ -23,6 +23,7 @@ export namespace ${simpleClassName}Api {
23 23 #end
24 24 #end
25 25 }
  26 +
26 27 #end
27 28 /** ${table.classComment}信息 */
28 29 export interface ${simpleClassName} {
... ... @@ -104,6 +105,7 @@ export function export${simpleClassName}(params: any) {
104 105 #set ($subClassNameVar = $subClassNameVars.get($index))
105 106  
106 107 // ==================== 子表($subTable.classComment) ====================
  108 +
107 109 ## 情况一:MASTER_ERP 时,需要分查询页子表
108 110 #if ( $table.templateType == 11 )
109 111 /** 获得${subTable.classComment}分页 */
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm
... ... @@ -88,7 +88,7 @@ export function useFormSchema(): VbenFormSchema[] {
88 88 maxCount: 1,
89 89 },
90 90 #elseif($column.htmlType == "editor")## 文本编辑器
91   - component: 'Editor',
  91 + component: 'RichTextarea',
92 92 #elseif($column.htmlType == "select")## 下拉框
93 93 component: 'Select',
94 94 componentProps: {
... ... @@ -279,6 +279,7 @@ export function useGridColumns(
279 279 #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
280 280 #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
281 281 // ==================== 子表($subTable.classComment) ====================
  282 +
282 283 #if ($table.templateType == 11) ## erp 情况
283 284 /** 新增/修改的表单 */
284 285 export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
... ... @@ -331,7 +332,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
331 332 maxCount: 1,
332 333 },
333 334 #elseif($column.htmlType == "editor")## 文本编辑器
334   - component: 'Editor',
  335 + component: 'RichTextarea',
335 336 #elseif($column.htmlType == "select")## 下拉框
336 337 component: 'Select',
337 338 componentProps: {
... ... @@ -391,6 +392,56 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
391 392 #end
392 393 ];
393 394 }
  395 +
  396 +/** 列表的搜索表单 */
  397 +export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
  398 + return [
  399 + #foreach($column in $subColumns)
  400 + #if ($column.listOperation)
  401 + #set ($dictType = $column.dictType)
  402 + #set ($javaType = $column.javaType)
  403 + #set ($javaField = $column.javaField)
  404 + #set ($comment = $column.columnComment)
  405 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  406 + #set ($dictMethod = "number")
  407 + #elseif ($javaType == "String")
  408 + #set ($dictMethod = "string")
  409 + #elseif ($javaType == "Boolean")
  410 + #set ($dictMethod = "boolean")
  411 + #end
  412 + {
  413 + fieldName: '${javaField}',
  414 + label: '${comment}',
  415 + #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
  416 + component: 'Input',
  417 + componentProps: {
  418 + allowClear: true,
  419 + placeholder: '请输入${comment}',
  420 + },
  421 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
  422 + component: 'Select',
  423 + componentProps: {
  424 + allowClear: true,
  425 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  426 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  427 + #else## 未设置 dictType 数据字典的情况
  428 + options: [],
  429 + #end
  430 + placeholder: '请选择${comment}',
  431 + },
  432 + #elseif($column.htmlType == "datetime")
  433 + component: 'RangePicker',
  434 + componentProps: {
  435 + ...getRangePickerDefaultProps(),
  436 + allowClear: true,
  437 + },
  438 + #end
  439 + },
  440 + #end
  441 + #end
  442 + ];
  443 +}
  444 +
394 445 /** 列表的字段 */
395 446 export function use${subSimpleClassName}GridColumns(
396 447 onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
... ... @@ -434,17 +485,18 @@ export function use${subSimpleClassName}GridColumns(
434 485 options: [
435 486 {
436 487 code: 'edit',
437   - show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:update']),
  488 + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']),
438 489 },
439 490 {
440 491 code: 'delete',
441   - show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:delete']),
  492 + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
442 493 },
443 494 ],
444 495 },
445 496 },
446 497 ];
447 498 }
  499 +
448 500 #else
449 501 #if ($subTable.subJoinMany) ## 一对多
450 502 /** 新增/修改列表的字段 */
... ... @@ -510,6 +562,7 @@ export function use${subSimpleClassName}GridColumns(
510 562 },
511 563 ];
512 564 }
  565 +
513 566 #else
514 567 /** 新增/修改的表单 */
515 568 export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
... ... @@ -562,7 +615,7 @@ export function use${subSimpleClassName}GridColumns(
562 615 maxCount: 1,
563 616 },
564 617 #elseif($column.htmlType == "editor")## 文本编辑器
565   - component: 'Editor',
  618 + component: 'RichTextarea',
566 619 #elseif($column.htmlType == "select")## 下拉框
567 620 component: 'Select',
568 621 componentProps: {
... ... @@ -622,6 +675,7 @@ export function use${subSimpleClassName}GridColumns(
622 675 #end
623 676 ];
624 677 }
  678 +
625 679 #end
626 680 #if ($table.templateType == 12) ## 内嵌情况
627 681 /** 列表的字段 */
... ... @@ -649,6 +703,7 @@ export function use${subSimpleClassName}GridColumns(
649 703 #end
650 704 ];
651 705 }
  706 +
652 707 #end
653 708 #end
654 709 #end
655 710 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/form.vue.vm
... ... @@ -6,7 +6,9 @@ import { message, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGro
6 6 ## 特殊:主子表专属逻辑
7 7 #if ( $table.templateType == 10 || $table.templateType == 12 )
8 8 #foreach ($subSimpleClassName in $subSimpleClassNames)
9   - import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
  9 + #set ($index = $foreach.count - 1)
  10 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  11 + import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
10 12 #end
11 13 #end
12 14  
... ... @@ -125,9 +127,7 @@ const [Modal, modalApi] = useVbenModal({
125 127 if (!data) {
126 128 return;
127 129 }
128   -
129 130 if (data.id) {
130   - // 编辑
131 131 modalApi.lock();
132 132 try {
133 133 data = await get${simpleClassName}(data.id);
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm
... ... @@ -10,7 +10,9 @@ import Form from &#39;./modules/form.vue&#39;;
10 10 ## 特殊:主子表专属逻辑
11 11 #if ( $table.templateType == 11 || $table.templateType == 12 )
12 12 #foreach ($subSimpleClassName in $subSimpleClassNames)
13   - import ${subSimpleClassName}List from './modules/${subSimpleClassName}List.vue'
  13 + #set ($index = $foreach.count - 1)
  14 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  15 + import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue'
14 16 #end
15 17 #end
16 18  
... ... @@ -26,9 +28,12 @@ import { downloadByData } from &#39;#/utils/download&#39;;
26 28  
27 29 import { useGridColumns, useGridFormSchema } from './data';
28 30  
29   -#if ($table.templateType == 12) ## 内嵌情况
  31 +#if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况
30 32 /** 子表的列表 */
31 33 const subTabsName = ref('$subClassNameVars.get(0)')
  34 +#if ($table.templateType == 11)
  35 +const select${simpleClassName} = ref<${simpleClassName}Api.${simpleClassName}>();
  36 +#end
32 37 #end
33 38  
34 39 const [FormModal, formModalApi] = useVbenModal({
... ... @@ -54,12 +59,6 @@ function onRefresh() {
54 59 #end
55 60 }
56 61  
57   -/** 导出表格 */
58   -async function onExport() {
59   - const data = await export${simpleClassName}(await gridApi.formApi.getValues());
60   - downloadByData(data, '${table.classComment}.xls');
61   -}
62   -
63 62 /** 创建${table.classComment} */
64 63 function onCreate() {
65 64 formModalApi.setData({}).open();
... ... @@ -96,6 +95,12 @@ async function onDelete(row: ${simpleClassName}Api.${simpleClassName}) {
96 95 }
97 96 }
98 97  
  98 +/** 导出表格 */
  99 +async function onExport() {
  100 + const data = await export${simpleClassName}(await gridApi.formApi.getValues());
  101 + downloadByData(data, '${table.classComment}.xls');
  102 +}
  103 +
99 104 /** 表格操作按钮的回调函数 */
100 105 function onActionClick({
101 106 code,
... ... @@ -108,14 +113,14 @@ function onActionClick({
108 113 break;
109 114 }
110 115 #end
111   - case 'delete': {
112   - onDelete(row);
113   - break;
114   - }
115 116 case 'edit': {
116 117 onEdit(row);
117 118 break;
118 119 }
  120 + case 'delete': {
  121 + onDelete(row);
  122 + break;
  123 + }
119 124 }
120 125 }
121 126  
... ... @@ -125,7 +130,11 @@ const [Grid, gridApi] = useVbenVxeGrid({
125 130 },
126 131 gridOptions: {
127 132 columns: useGridColumns(onActionClick),
  133 +#if (${table.templateType} == 11)
  134 + height: '600px',
  135 +#else
128 136 height: 'auto',
  137 +#end
129 138 #if (${table.templateType} == 2)## 树表设置
130 139 treeConfig: {
131 140 parentField: '${treeParentColumn.javaField}',
... ... @@ -162,12 +171,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
162 171 rowConfig: {
163 172 keyField: 'id',
164 173 isHover: true,
  174 +#if (${table.templateType} == 11)
  175 + isCurrent: true,
  176 +#end
165 177 },
166 178 toolbarConfig: {
167 179 refresh: { code: 'query' },
168 180 search: true,
169 181 },
170 182 } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
  183 +#if (${table.templateType} == 11)
  184 + gridEvents:{
  185 + cellClick: ({ row }: { row: ${simpleClassName}Api.${simpleClassName}}) => {
  186 + select${simpleClassName}.value = row;
  187 + },
  188 + }
  189 +#end
171 190 });
172 191 </script>
173 192  
... ... @@ -175,11 +194,14 @@ const [Grid, gridApi] = useVbenVxeGrid({
175 194 <Page auto-content-height>
176 195 <FormModal @success="onRefresh" />
177 196  
  197 +#if ($table.templateType == 11) ## erp情况
  198 + <div>
  199 +#end
178 200 <Grid table-title="${table.classComment}列表">
179 201 #if ($table.templateType == 12) ## 内嵌情况
180 202 <template #expand_content="{ row }">
181 203 <!-- 子表的表单 -->
182   - <Tabs v-model:active-key="subTabsName">
  204 + <Tabs v-model:active-key="subTabsName" class="mx-8">
183 205 #foreach ($subTable in $subTables)
184 206 #set ($index = $foreach.count - 1)
185 207 #set ($subClassNameVar = $subClassNameVars.get($index))
... ... @@ -212,5 +234,21 @@ const [Grid, gridApi] = useVbenVxeGrid({
212 234 </Button>
213 235 </template>
214 236 </Grid>
  237 +
  238 +#if ($table.templateType == 11) ## erp情况
  239 + <!-- 子表的表单 -->
  240 + <Tabs v-model:active-key="subTabsName" class="mt-2">
  241 + #foreach ($subTable in $subTables)
  242 + #set ($index = $foreach.count - 1)
  243 + #set ($subClassNameVar = $subClassNameVars.get($index))
  244 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  245 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  246 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  247 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" />
  248 + </Tabs.TabPane>
  249 + #end
  250 + </Tabs>
  251 + </div>
  252 +#end
215 253 </Page>
216 254 </template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_erp.vue.vm
... ... @@ -2,192 +2,85 @@
2 2 #set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
3 3 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
5   -#set ($subClassNameVar = $subClassNameVars.get($subIndex))
6   -#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
7 5 <script lang="ts" setup>
8 6 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
9 7  
10   - import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
11   - import { $t } from '#/locales';
12   -
13   -#if ($subTable.subJoinMany) ## 一对多
14   -import { Plus } from "@vben/icons";
15   -import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
16   -import type { OnActionClickParams } from '#/adapter/vxe-table';
17   -import { useVbenVxeGrid } from '#/adapter/vxe-table';
18   -import { use${subSimpleClassName}GridColumns } from '../data';
19   -import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
20   -#else
21   -import { useVbenForm } from '#/adapter/form';
22   -import { use${subSimpleClassName}FormSchema } from '../data';
23   -import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
24   -#end
25   -
26   -const props = defineProps<{
27   - ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
28   -}>()
29   -
30   -#if ($subTable.subJoinMany) ## 一对多
31   -/** 表格操作按钮的回调函数 */
32   -function onActionClick({
33   - code,
34   - row,
35   - }: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
36   -switch (code) {
37   - case 'delete': {
38   - onDelete(row);
39   - break;
40   - }
41   -}
42   -}
  8 + import { useVbenModal } from '@vben/common-ui';
  9 + import { message } from 'ant-design-vue';
43 10  
44   -const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
45   -gridOptions: {
46   - columns: use${subSimpleClassName}GridColumns(onActionClick),
47   - border: true,
48   - showOverflow: true,
49   - autoResize: true,
50   - keepSource: true,
51   - rowConfig: {
52   - keyField: 'id',
53   - },
54   - pagerConfig: {
55   - enabled: false,
56   - },
57   - toolbarConfig: {
58   - enabled: false,
59   - },
60   -},
61   -});
62   -
63   -/** 删除${subTable.classComment} */
64   -const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
65   -await ${subClassNameVar}GridApi.grid.remove(row);
66   -}
67   -
68   -/** 添加${subTable.classComment} */
69   -const handleAdd = async () => {
70   -await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
71   -}
  11 + import { computed, ref } from 'vue';
  12 + import { $t } from '#/locales';
  13 + import { useVbenForm } from '#/adapter/form';
  14 + import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
72 15  
73   -/** 提供获取表格数据的方法供父组件调用 */
74   -defineExpose({
75   -getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
76   - return [
77   - ...${subClassNameVar}GridApi.grid.getData(),
78   - ...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
79   - delete row.id;
80   - return row;
81   - }),
82   - ];
83   -},
84   -});
  16 + import { use${subSimpleClassName}FormSchema } from '../data';
85 17  
86   -/** 监听主表的关联字段的变化,加载对应的子表数据 */
87   -watch(
88   - () => props.${subJoinColumn.javaField},
89   - async (val) => {
90   - if (!val) {
91   - return;
92   - }
  18 + const emit = defineEmits(['success']);
  19 + const formData = ref<${simpleClassName}Api.${subSimpleClassName}>();
  20 + const getTitle = computed(() => {
  21 + return formData.value?.id
  22 + ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
  23 + : $t('ui.actionTitle.create', ['${subTable.classComment}']);
  24 + });
93 25  
94   - await nextTick();
95   - await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
96   - },
97   -);
98   -#else
99   -const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
100   -layout: 'horizontal',
101   -schema: use${subSimpleClassName}FormSchema(),
102   -showDefaultActions: false
103   -});
  26 + const [Form, formApi] = useVbenForm({
  27 + layout: 'horizontal',
  28 + schema: use${subSimpleClassName}FormSchema(),
  29 + showDefaultActions: false
  30 + });
104 31  
105   -/** 暴露出表单校验方法和表单值获取方法 */
106   -defineExpose({
107   -validate: async () => {
108   - const { valid } = await ${subClassNameVar}FormApi.validate();
109   - return valid;
110   -},
111   -getValues: ${subClassNameVar}FormApi.getValues,
112   -});
  32 + const [Modal, modalApi] = useVbenModal({
  33 + async onConfirm() {
  34 + const { valid } = await formApi.validate();
  35 + if (!valid) {
  36 + return;
  37 + }
113 38  
114   -/** 监听主表的关联字段的变化,加载对应的子表数据 */
115   -watch(
116   - () => props.${subJoinColumn.javaField},
117   - async (val) => {
118   - if (!val) {
119   - return;
120   - }
  39 + modalApi.lock();
  40 + // 提交表单
  41 + const data = (await formApi.getValues()) as ${simpleClassName}Api.${subSimpleClassName};
  42 + data.${subJoinColumn.javaField} = formData.value?.${subJoinColumn.javaField};
  43 + try {
  44 + await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
  45 + // 关闭并提示
  46 + await modalApi.close();
  47 + emit('success');
  48 + message.success({
  49 + content: $t('ui.actionMessage.operationSuccess'),
  50 + key: 'action_process_msg',
  51 + });
  52 + } finally {
  53 + modalApi.lock(false);
  54 + }
  55 + },
  56 + async onOpenChange(isOpen: boolean) {
  57 + if (!isOpen) {
  58 + formData.value = undefined;
  59 + return;
  60 + }
121 61  
122   - await nextTick();
123   - await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
124   - },
125   -);
126   -#end
  62 + // 加载数据
  63 + let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
  64 + if (!data) {
  65 + return;
  66 + }
  67 + if (data.id) {
  68 + modalApi.lock();
  69 + try {
  70 + data = await get${subSimpleClassName}(data.id);
  71 + } finally {
  72 + modalApi.lock(false);
  73 + }
  74 + }
  75 + // 设置到 values
  76 + formData.value = data;
  77 + await formApi.setValues(formData.value);
  78 + },
  79 + });
127 80 </script>
128 81  
129 82 <template>
130   - #if ($subTable.subJoinMany) ## 一对多
131   - <${subSimpleClassName}Grid class="mx-4">
132   - #foreach($column in $subColumns)
133   - #if ($column.createOperation || $column.updateOperation)
134   - #set ($javaField = $column.javaField)
135   - #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
136   - #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
137   - <template #${javaField}="{ row }">
138   - <Input v-model:value="row.${javaField}" />
139   - </template>
140   - #elseif($column.htmlType == "imageUpload")## 图片上传
141   - <template #${javaField}="{ row }">
142   - <UploadImg v-model:value="row.${javaField}" />
143   - </template>
144   - #elseif($column.htmlType == "fileUpload")## 文件上传
145   - <template #${javaField}="{ row }">
146   - <UploadFile v-model:value="row.${javaField}" />
147   - </template>
148   - #elseif($column.htmlType == "editor")## 文本编辑器
149   - <template #${javaField}="{ row }">
150   - <Textarea v-model:value="row.${javaField}" />
151   - </template>
152   - #elseif($column.htmlType == "select")## 下拉框
153   - <template #${javaField}="{ row, column }">
154   - <Select v-model:value="row.${javaField}" class="w-full">
155   - <Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
156   - {{ option.label }}
157   - </Select.Option>
158   - </Select>
159   - </template>
160   - #elseif($column.htmlType == "checkbox")## 多选框
161   - <template #${javaField}="{ row, column }">
162   - <CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
163   - </template>
164   - #elseif($column.htmlType == "radio")## 单选框
165   - <template #${javaField}="{ row, column }">
166   - <RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
167   - </template>
168   - #elseif($column.htmlType == "datetime")## 时间框
169   - <template #${javaField}="{ row }">
170   - <DatePicker
171   - v-model:value="row.${javaField}"
172   - :showTime="true"
173   - format="YYYY-MM-DD HH:mm:ss"
174   - valueFormat='x'
175   - />
176   - </template>
177   - #elseif($column.htmlType == "textarea")## 文本框
178   - <template #${javaField}="{ row }">
179   - <Textarea v-model:value="row.${javaField}" />
180   - </template>
181   - #end
182   - #end
183   - #end
184   - </${subSimpleClassName}Grid>
185   - <div class="flex justify-center">
186   - <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
187   - {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
188   - </Button>
189   - </div>
190   - #else
191   - <${subSimpleClassName}Form class="mx-4" />
192   - #end
  83 + <Modal :title="getTitle">
  84 + <Form class="mx-4" />
  85 + </Modal>
193 86 </template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm
... ... @@ -24,7 +24,7 @@ import { get${subSimpleClassName}By${SubJoinColumnName} } from &#39;#/api/${table.mo
24 24 #end
25 25  
26 26 const props = defineProps<{
27   - ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
  27 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
28 28 }>()
29 29  
30 30 #if ($subTable.subJoinMany) ## 一对多
... ... @@ -41,7 +41,7 @@ function onActionClick({
41 41 }
42 42 }
43 43  
44   -const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
  44 +const [Grid, gridApi] = useVbenVxeGrid({
45 45 gridOptions: {
46 46 columns: use${subSimpleClassName}GridEditColumns(onActionClick),
47 47 border: true,
... ... @@ -60,34 +60,25 @@ gridOptions: {
60 60 },
61 61 });
62 62  
63   -/** 删除${subTable.classComment} */
64   -const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
65   - await ${subClassNameVar}GridApi.grid.remove(row);
  63 +/** 添加${subTable.classComment} */
  64 +const onAdd = async () => {
  65 + await gridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
66 66 }
67 67  
68   -/** 添加${subTable.classComment} */
69   -const handleAdd = async () => {
70   - await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  68 +/** 删除${subTable.classComment} */
  69 +const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  70 + await gridApi.grid.remove(row);
71 71 }
72 72  
73 73 /** 提供获取表格数据的方法供父组件调用 */
74 74 defineExpose({
75 75 getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
76   - // 获取当前数据,但排除已删除的记录
77   - const allData = ${subClassNameVar}GridApi.grid.getData();
78   - const removedData = ${subClassNameVar}GridApi.grid.getRemoveRecords();
79   - const removedIds = new Set(removedData.map((row) => row.id));
80   -
81   - // 过滤掉已删除的记录
82   - const currentData = allData.filter((row) => !removedIds.has(row.id));
83   -
84   - // 获取新插入的记录并移除id
85   - const insertedData = ${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
86   - delete row.id;
87   - return row;
88   - });
89   -
90   - return [...currentData, ...insertedData];
  76 + const data = gridApi.grid.getData() as ${simpleClassName}Api.${subSimpleClassName}[];
  77 + const removeRecords = gridApi.grid.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  78 + const insertRecords = gridApi.grid.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  79 + return data
  80 + .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
  81 + .concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
91 82 },
92 83 });
93 84  
... ... @@ -98,14 +89,13 @@ watch(
98 89 if (!val) {
99 90 return;
100 91 }
101   -
102 92 await nextTick();
103   - await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  93 + await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
104 94 },
105 95 { immediate: true },
106 96 );
107 97 #else
108   -const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
  98 +const [Form, formApi] = useVbenForm({
109 99 layout: 'horizontal',
110 100 schema: use${subSimpleClassName}FormSchema(),
111 101 showDefaultActions: false
... ... @@ -114,10 +104,10 @@ showDefaultActions: false
114 104 /** 暴露出表单校验方法和表单值获取方法 */
115 105 defineExpose({
116 106 validate: async () => {
117   - const { valid } = await ${subClassNameVar}FormApi.validate();
  107 + const { valid } = await formApi.validate();
118 108 return valid;
119 109 },
120   - getValues: ${subClassNameVar}FormApi.getValues,
  110 + getValues: formApi.getValues,
121 111 });
122 112  
123 113 /** 监听主表的关联字段的变化,加载对应的子表数据 */
... ... @@ -127,9 +117,8 @@ watch(
127 117 if (!val) {
128 118 return;
129 119 }
130   -
131 120 await nextTick();
132   - await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  121 + await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
133 122 },
134 123 { immediate: true },
135 124 );
... ... @@ -138,7 +127,7 @@ watch(
138 127  
139 128 <template>
140 129 #if ($subTable.subJoinMany) ## 一对多
141   - <${subSimpleClassName}Grid class="mx-4">
  130 + <Grid class="mx-4">
142 131 #foreach($column in $subColumns)
143 132 #if ($column.createOperation || $column.updateOperation)
144 133 #set ($javaField = $column.javaField)
... ... @@ -191,13 +180,13 @@ watch(
191 180 #end
192 181 #end
193 182 #end
194   - </${subSimpleClassName}Grid>
195   - <div class="flex justify-center">
196   - <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
  183 + </Grid>
  184 + <div class="flex justify-center -mt-4">
  185 + <Button :icon="h(Plus)" type="primary" ghost @click="onAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
197 186 {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
198 187 </Button>
199 188 </div>
200 189 #else
201   - <${subSimpleClassName}Form class="mx-4" />
  190 + <Form class="mx-4" />
202 191 #end
203 192 </template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm
... ... @@ -3,32 +3,37 @@
3 3 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
5 5 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
6   -#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  6 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
7 7 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
8 8 <script lang="ts" setup>
9 9 import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
10 10 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
11 11  
  12 +#if ($table.templateType == 11) ## erp
  13 + import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
  14 +#end
12 15 import { useVbenModal } from '@vben/common-ui';
13 16 import { Button, message } from 'ant-design-vue';
14 17 import { Plus } from '@vben/icons';
15   - import { ref, h, nextTick,watch } from 'vue';
  18 + import { #if($table.templateType != 11)ref,#end h, nextTick,watch } from 'vue';
16 19 import { $t } from '#/locales';
17 20 import { useVbenVxeGrid } from '#/adapter/vxe-table';
18 21  
19 22  
20 23 #if ($table.templateType == 11) ## erp
21   - import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
22   -#end
  24 + import { delete${subSimpleClassName}, get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  25 + import { use${subSimpleClassName}GridFormSchema, use${subSimpleClassName}GridColumns } from '../data';
  26 + #else
  27 + #if ($subTable.subJoinMany) ## 一对多
  28 + import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  29 + #else
  30 + import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  31 + #end
23 32 import { use${subSimpleClassName}GridColumns } from '../data';
24   -#if ($subTable.subJoinMany) ## 一对多
25   -import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
26   -#else
27   -import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
28 33 #end
29 34  
30 35 const props = defineProps<{
31   - ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
  36 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
32 37 }>()
33 38  
34 39 #if ($table.templateType == 11) ## erp
... ... @@ -39,13 +44,18 @@ const props = defineProps&lt;{
39 44  
40 45 /** 创建${subTable.classComment} */
41 46 function onCreate() {
42   - formModalApi.setData({}).open();
  47 + if (!props.${subJoinColumn.javaField}){
  48 + message.warning("请先选择一个${table.classComment}!")
  49 + return
  50 + }
  51 + formModalApi.setData({${subJoinColumn.javaField}: props.${subJoinColumn.javaField}}).open();
43 52 }
44 53  
45 54 /** 编辑${subTable.classComment} */
46 55 function onEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
47 56 formModalApi.setData(row).open();
48 57 }
  58 +
49 59 /** 删除${subTable.classComment} */
50 60 async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
51 61 const hideLoading = message.loading({
... ... @@ -71,45 +81,77 @@ function onActionClick({
71 81 row,
72 82 }: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
73 83 switch (code) {
74   - case 'delete': {
75   - onDelete(row);
76   - break;
77   - }
78 84 case 'edit': {
79 85 onEdit(row);
80 86 break;
81 87 }
  88 + case 'delete': {
  89 + onDelete(row);
  90 + break;
  91 + }
82 92 }
83 93 }
  94 +
84 95 #end
85 96 const [Grid, gridApi] = useVbenVxeGrid({
  97 +#if ($table.templateType == 11)
  98 + formOptions: {
  99 + schema: use${subSimpleClassName}GridFormSchema(),
  100 + },
  101 +#end
86 102 gridOptions: {
87 103 #if ($table.templateType == 11)
88   - columns: use${subSimpleClassName}GridColumns(onActionClick),
  104 + columns: use${subSimpleClassName}GridColumns(onActionClick),
  105 + proxyConfig: {
  106 + ajax: {
  107 + query: async ({ page }, formValues) => {
  108 + if (!props.${subJoinColumn.javaField}){
  109 + return []
  110 + }
  111 + return await get${subSimpleClassName}Page({
  112 + pageNo: page.currentPage,
  113 + pageSize: page.pageSize,
  114 + ${subJoinColumn.javaField}: props.${subJoinColumn.javaField},
  115 + ...formValues,
  116 + });
  117 + },
  118 + },
  119 + },
  120 + pagerConfig: {
  121 + enabled: true,
  122 + },
  123 + toolbarConfig: {
  124 + refresh: { code: 'query' },
  125 + search: true,
  126 + },
89 127 #else
90   - columns: use${subSimpleClassName}GridColumns(),
  128 + columns: use${subSimpleClassName}GridColumns(),
  129 + pagerConfig: {
  130 + enabled: false,
  131 + },
  132 + toolbarConfig: {
  133 + enabled: false,
  134 + },
91 135 #end
92   - height: 'auto',
93   - rowConfig: {
  136 + height: '600px',
  137 + rowConfig: {
94 138 keyField: 'id',
95 139 isHover: true,
96   - },
97   - pagerConfig: {
98   - enabled: false,
99   - },
100   - toolbarConfig: {
101   - enabled: false,
102   - },
103   - } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
  140 + },
  141 + } as VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>,
104 142 });
105 143  
106 144 /** 刷新表格 */
107 145 const onRefresh = async ()=> {
108   - #if ($subTable.subJoinMany) ## 一对多
  146 +#if ($table.templateType == 11) ## erp
  147 + await gridApi.query();
  148 +#else
  149 + #if ($subTable.subJoinMany) ## 一对多
109 150 await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
110   - #else
  151 + #else
111 152 await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
112   - #end
  153 + #end
  154 +#end
113 155 }
114 156  
115 157 /** 监听主表的关联字段的变化,加载对应的子表数据 */
... ... @@ -119,7 +161,6 @@ const onRefresh = async ()=&gt; {
119 161 if (!val) {
120 162 return;
121 163 }
122   -
123 164 await nextTick();
124 165 await onRefresh()
125 166 },
... ... @@ -128,18 +169,16 @@ const onRefresh = async ()=&gt; {
128 169 </script>
129 170  
130 171 <template>
131   - <div class="mx-4">
132   - #if ($table.templateType == 11) ## erp
133   - <FormModal @success="onRefresh" />
134   - <Grid table-title="${subTable.classComment}列表">
135   - <template #toolbar-tools>
136   - <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${subTable.moduleName}:${subSimpleClassName_strikeCase}:create']">
137   - {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
138   - </Button>
139   - </template>
140   - </Grid>
141   - #else
142   - <Grid table-title="${subTable.classComment}列表" />
143   - #end
144   - </div>
  172 + #if ($table.templateType == 11) ## erp
  173 + <FormModal @success="onRefresh" />
  174 + <Grid table-title="${subTable.classComment}列表">
  175 + <template #toolbar-tools>
  176 + <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:create']">
  177 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  178 + </Button>
  179 + </template>
  180 + </Grid>
  181 + #else
  182 + <Grid table-title="${subTable.classComment}列表" />
  183 + #end
145 184 </template>
146 185 \ No newline at end of file
... ...