Преглед изворни кода

!1328 【功能新增】代码生成: vue3_vben5_antd schema 主子表 erp 模板
Merge pull request !1328 from puhui999/master-jdk17

芋道源码 пре 1 година
родитељ
комит
6d179320c9

+ 7 - 5
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 {
             .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("api/api.ts"),
                     vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
             .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_normal.vue"),  // 特殊:主子表专属逻辑
-                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
+                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
             .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_inner.vue"),  // 特殊:主子表专属逻辑
-                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
+                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
             .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_erp.vue"),  // 特殊:主子表专属逻辑
-                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
+                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
             .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_inner.vue"),  // 特殊:主子表专属逻辑
-                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}List.vue"))
+                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
             .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_erp.vue"),  // 特殊:主子表专属逻辑
-                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}List.vue"))
+                    vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
             .build();
 
     @Resource
@@ -451,6 +451,8 @@ public class CodegenEngine {
             filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName());
             filePath = StrUtil.replace(filePath, "${subSimpleClassName}",
                     ((List<String>) bindingMap.get("subSimpleClassNames")).get(subIndex));
+            filePath = StrUtil.replace(filePath, "${subSimpleClassName_strikeCase}",
+                    ((List<String>) bindingMap.get("subSimpleClassName_strikeCases")).get(subIndex));
         }
         return filePath;
     }

+ 2 - 0
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 {
       #end
     #end
   }
+
 #end
   /** ${table.classComment}信息 */
   export interface ${simpleClassName} {
@@ -104,6 +105,7 @@ export function export${simpleClassName}(params: any) {
 #set ($subClassNameVar = $subClassNameVars.get($index))
 
 // ==================== 子表($subTable.classComment) ====================
+
 ## 情况一:MASTER_ERP 时,需要分查询页子表
 #if ( $table.templateType == 11 )
 /** 获得${subTable.classComment}分页 */

+ 60 - 5
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[] {
         maxCount: 1,
       },
   #elseif($column.htmlType == "editor")## 文本编辑器
-      component: 'Editor',
+      component: 'RichTextarea',
   #elseif($column.htmlType == "select")## 下拉框
       component: 'Select',
       componentProps: {
@@ -279,6 +279,7 @@ export function useGridColumns(
     #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
     #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
 // ==================== 子表($subTable.classComment) ====================
+
 #if ($table.templateType == 11) ## erp 情况
 /** 新增/修改的表单 */
 export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
@@ -331,7 +332,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
                                     maxCount: 1,
                                 },
                             #elseif($column.htmlType == "editor")## 文本编辑器
-                                component: 'Editor',
+                                component: 'RichTextarea',
                             #elseif($column.htmlType == "select")## 下拉框
                                 component: 'Select',
                                 componentProps: {
@@ -391,6 +392,56 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
         #end
     ];
 }
+
+/** 列表的搜索表单 */
+export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
+    return [
+        #foreach($column in $subColumns)
+            #if ($column.listOperation)
+                #set ($dictType = $column.dictType)
+                #set ($javaType = $column.javaType)
+                #set ($javaField = $column.javaField)
+                #set ($comment = $column.columnComment)
+                #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
+                    #set ($dictMethod = "number")
+                #elseif ($javaType == "String")
+                    #set ($dictMethod = "string")
+                #elseif ($javaType == "Boolean")
+                    #set ($dictMethod = "boolean")
+                #end
+                {
+                    fieldName: '${javaField}',
+                    label: '${comment}',
+                    #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
+                        component: 'Input',
+                        componentProps: {
+                            allowClear: true,
+                            placeholder: '请输入${comment}',
+                        },
+                    #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
+                        component: 'Select',
+                        componentProps: {
+                            allowClear: true,
+                            #if ("" != $dictType)## 设置了 dictType 数据字典的情况
+                                options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
+                            #else## 未设置 dictType 数据字典的情况
+                                options: [],
+                            #end
+                            placeholder: '请选择${comment}',
+                        },
+                    #elseif($column.htmlType == "datetime")
+                        component: 'RangePicker',
+                        componentProps: {
+                            ...getRangePickerDefaultProps(),
+                            allowClear: true,
+                        },
+                    #end
+                },
+            #end
+        #end
+    ];
+}
+
 /** 列表的字段 */
 export function use${subSimpleClassName}GridColumns(
     onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
@@ -434,17 +485,18 @@ export function use${subSimpleClassName}GridColumns(
                 options: [
                     {
                         code: 'edit',
-                        show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:update']),
+                        show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']),
                     },
                     {
                         code: 'delete',
-                        show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:delete']),
+                        show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
                     },
                 ],
             },
         },
     ];
 }
+
 #else
     #if ($subTable.subJoinMany) ## 一对多
     /** 新增/修改列表的字段 */
@@ -510,6 +562,7 @@ export function use${subSimpleClassName}GridColumns(
             },
         ];
     }
+
     #else
     /** 新增/修改的表单 */
     export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
@@ -562,7 +615,7 @@ export function use${subSimpleClassName}GridColumns(
                                         maxCount: 1,
                                     },
                                 #elseif($column.htmlType == "editor")## 文本编辑器
-                                    component: 'Editor',
+                                    component: 'RichTextarea',
                                 #elseif($column.htmlType == "select")## 下拉框
                                     component: 'Select',
                                     componentProps: {
@@ -622,6 +675,7 @@ export function use${subSimpleClassName}GridColumns(
             #end
         ];
     }
+
     #end
     #if ($table.templateType == 12) ## 内嵌情况
     /** 列表的字段 */
@@ -649,6 +703,7 @@ export function use${subSimpleClassName}GridColumns(
             #end
         ];
     }
+
     #end
 #end
 #end

+ 3 - 3
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
 ## 特殊:主子表专属逻辑
 #if ( $table.templateType == 10 || $table.templateType == 12 )
   #foreach ($subSimpleClassName in $subSimpleClassNames)
-  import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
+  #set ($index = $foreach.count - 1)
+  #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
+  import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
   #end
 #end
 
@@ -125,9 +127,7 @@ const [Modal, modalApi] = useVbenModal({
     if (!data) {
       return;
     }
-
     if (data.id) {
-      // 编辑
       modalApi.lock();
       try {
         data = await get${simpleClassName}(data.id);

+ 51 - 13
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 './modules/form.vue';
 ## 特殊:主子表专属逻辑
 #if ( $table.templateType == 11 || $table.templateType == 12 )
     #foreach ($subSimpleClassName in $subSimpleClassNames)
-    import ${subSimpleClassName}List from './modules/${subSimpleClassName}List.vue'
+    #set ($index = $foreach.count - 1)
+    #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
+    import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue'
     #end
 #end
 
@@ -26,9 +28,12 @@ import { downloadByData } from '#/utils/download';
 
 import { useGridColumns, useGridFormSchema } from './data';
 
-#if ($table.templateType == 12) ## 内嵌情况
+#if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况
 /** 子表的列表 */
 const subTabsName = ref('$subClassNameVars.get(0)')
+#if ($table.templateType == 11)
+const select${simpleClassName} = ref<${simpleClassName}Api.${simpleClassName}>();
+#end
 #end
 
 const [FormModal, formModalApi] = useVbenModal({
@@ -54,12 +59,6 @@ function onRefresh() {
 #end
 }
 
-/** 导出表格 */
-async function onExport() {
-  const data = await export${simpleClassName}(await gridApi.formApi.getValues());
-  downloadByData(data, '${table.classComment}.xls');
-}
-
 /** 创建${table.classComment} */
 function onCreate() {
   formModalApi.setData({}).open();
@@ -96,6 +95,12 @@ async function onDelete(row: ${simpleClassName}Api.${simpleClassName}) {
   }
 }
 
+/** 导出表格 */
+async function onExport() {
+  const data = await export${simpleClassName}(await gridApi.formApi.getValues());
+  downloadByData(data, '${table.classComment}.xls');
+}
+
 /** 表格操作按钮的回调函数 */
 function onActionClick({
   code,
@@ -108,14 +113,14 @@ function onActionClick({
       break;
     }
   #end
-    case 'delete': {
-      onDelete(row);
-      break;
-    }
     case 'edit': {
       onEdit(row);
       break;
     }
+    case 'delete': {
+      onDelete(row);
+      break;
+    }
   }
 }
 
@@ -125,7 +130,11 @@ const [Grid, gridApi] = useVbenVxeGrid({
   },
   gridOptions: {
     columns: useGridColumns(onActionClick),
+#if (${table.templateType} == 11)
+    height: '600px',
+#else
     height: 'auto',
+#end
 #if (${table.templateType} == 2)## 树表设置
   treeConfig: {
     parentField: '${treeParentColumn.javaField}',
@@ -162,12 +171,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
     rowConfig: {
       keyField: 'id',
       isHover: true,
+#if (${table.templateType} == 11)
+      isCurrent: true,
+#end
     },
     toolbarConfig: {
       refresh: { code: 'query' },
       search: true,
     },
   } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
+#if (${table.templateType} == 11)
+  gridEvents:{
+    cellClick: ({ row }: { row: ${simpleClassName}Api.${simpleClassName}}) => {
+      select${simpleClassName}.value = row;
+    },
+  }
+#end
 });
 </script>
 
@@ -175,11 +194,14 @@ const [Grid, gridApi] = useVbenVxeGrid({
   <Page auto-content-height>
     <FormModal @success="onRefresh" />
 
+#if ($table.templateType == 11) ## erp情况
+  <div>
+#end
     <Grid table-title="${table.classComment}列表">
         #if ($table.templateType == 12) ## 内嵌情况
           <template #expand_content="{ row }">
             <!-- 子表的表单 -->
-            <Tabs v-model:active-key="subTabsName">
+            <Tabs v-model:active-key="subTabsName" class="mx-8">
                 #foreach ($subTable in $subTables)
                     #set ($index = $foreach.count - 1)
                     #set ($subClassNameVar = $subClassNameVars.get($index))
@@ -212,5 +234,21 @@ const [Grid, gridApi] = useVbenVxeGrid({
         </Button>
       </template>
     </Grid>
+
+#if ($table.templateType == 11) ## erp情况
+    <!-- 子表的表单 -->
+    <Tabs v-model:active-key="subTabsName" class="mt-2">
+        #foreach ($subTable in $subTables)
+            #set ($index = $foreach.count - 1)
+            #set ($subClassNameVar = $subClassNameVars.get($index))
+            #set ($subSimpleClassName = $subSimpleClassNames.get($index))
+            #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
+          <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
+            <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" />
+          </Tabs.TabPane>
+        #end
+    </Tabs>
+    </div>
+#end
   </Page>
 </template>

+ 68 - 175
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 @@
 #set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
-#set ($subClassNameVar = $subClassNameVars.get($subIndex))
-#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
 <script lang="ts" setup>
   import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 
-  import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
-  import { $t } from '#/locales';
-
-#if ($subTable.subJoinMany) ## 一对多
-import { Plus } from "@vben/icons";
-import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
-import type { OnActionClickParams } from '#/adapter/vxe-table';
-import { useVbenVxeGrid } from '#/adapter/vxe-table';
-import { use${subSimpleClassName}GridColumns } from '../data';
-import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
-#else
-import { useVbenForm } from '#/adapter/form';
-import { use${subSimpleClassName}FormSchema } from '../data';
-import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
-#end
-
-const props = defineProps<{
-  ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
-}>()
-
-#if ($subTable.subJoinMany) ## 一对多
-/** 表格操作按钮的回调函数 */
-function onActionClick({
-   code,
-   row,
- }: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
-switch (code) {
-  case 'delete': {
-    onDelete(row);
-    break;
-  }
-}
-}
+  import { useVbenModal } from '@vben/common-ui';
+  import { message } from 'ant-design-vue';
 
-const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
-gridOptions: {
-  columns: use${subSimpleClassName}GridColumns(onActionClick),
-  border: true,
-  showOverflow: true,
-  autoResize: true,
-  keepSource: true,
-  rowConfig: {
-    keyField: 'id',
-  },
-  pagerConfig: {
-    enabled: false,
-  },
-  toolbarConfig: {
-    enabled: false,
-  },
-},
-});
-
-/** 删除${subTable.classComment} */
-const onDelete =  async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
-await ${subClassNameVar}GridApi.grid.remove(row);
-}
-
-/** 添加${subTable.classComment} */
-const handleAdd = async () => {
-await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
-}
+  import { computed, ref } from 'vue';
+  import { $t } from '#/locales';
+  import { useVbenForm } from '#/adapter/form';
+  import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 
-/** 提供获取表格数据的方法供父组件调用 */
-defineExpose({
-getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
-  return [
-    ...${subClassNameVar}GridApi.grid.getData(),
-    ...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
-      delete row.id;
-      return row;
-    }),
-  ];
-},
-});
+  import { use${subSimpleClassName}FormSchema } from '../data';
 
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.${subJoinColumn.javaField},
-  async (val) => {
-    if (!val) {
-      return;
-    }
+  const emit = defineEmits(['success']);
+  const formData = ref<${simpleClassName}Api.${subSimpleClassName}>();
+  const getTitle = computed(() => {
+    return formData.value?.id
+        ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
+        : $t('ui.actionTitle.create', ['${subTable.classComment}']);
+  });
 
-    await nextTick();
-    await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
-  },
-);
-#else
-const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
-layout: 'horizontal',
-schema: use${subSimpleClassName}FormSchema(),
-showDefaultActions: false
-});
+  const [Form, formApi] = useVbenForm({
+    layout: 'horizontal',
+    schema: use${subSimpleClassName}FormSchema(),
+    showDefaultActions: false
+  });
 
-/** 暴露出表单校验方法和表单值获取方法 */
-defineExpose({
-validate: async () => {
-  const { valid } = await ${subClassNameVar}FormApi.validate();
-  return valid;
-},
-getValues: ${subClassNameVar}FormApi.getValues,
-});
+  const [Modal, modalApi] = useVbenModal({
+    async onConfirm() {
+      const { valid } = await formApi.validate();
+      if (!valid) {
+        return;
+      }
 
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.${subJoinColumn.javaField},
-  async (val) => {
-    if (!val) {
-      return;
-    }
+      modalApi.lock();
+      // 提交表单
+      const data = (await formApi.getValues()) as ${simpleClassName}Api.${subSimpleClassName};
+      data.${subJoinColumn.javaField} = formData.value?.${subJoinColumn.javaField};
+      try {
+        await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
+        // 关闭并提示
+        await modalApi.close();
+        emit('success');
+        message.success({
+          content: $t('ui.actionMessage.operationSuccess'),
+          key: 'action_process_msg',
+        });
+      } finally {
+        modalApi.lock(false);
+      }
+    },
+    async onOpenChange(isOpen: boolean) {
+      if (!isOpen) {
+        formData.value = undefined;
+        return;
+      }
 
-    await nextTick();
-    await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
-  },
-);
-#end
+      // 加载数据
+      let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
+      if (!data) {
+        return;
+      }
+      if (data.id) {
+        modalApi.lock();
+        try {
+          data = await get${subSimpleClassName}(data.id);
+        } finally {
+          modalApi.lock(false);
+        }
+      }
+      // 设置到 values
+      formData.value = data;
+      await formApi.setValues(formData.value);
+    },
+  });
 </script>
 
 <template>
-    #if ($subTable.subJoinMany) ## 一对多
-      <${subSimpleClassName}Grid class="mx-4">
-          #foreach($column in $subColumns)
-              #if ($column.createOperation || $column.updateOperation)
-                  #set ($javaField = $column.javaField)
-                  #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
-                  #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
-                    <template #${javaField}="{ row }">
-                      <Input v-model:value="row.${javaField}" />
-                    </template>
-                  #elseif($column.htmlType == "imageUpload")## 图片上传
-                    <template #${javaField}="{ row }">
-                      <UploadImg v-model:value="row.${javaField}" />
-                    </template>
-                  #elseif($column.htmlType == "fileUpload")## 文件上传
-                    <template #${javaField}="{ row }">
-                      <UploadFile v-model:value="row.${javaField}" />
-                    </template>
-                  #elseif($column.htmlType == "editor")## 文本编辑器
-                    <template #${javaField}="{ row }">
-                      <Textarea v-model:value="row.${javaField}" />
-                    </template>
-                  #elseif($column.htmlType == "select")## 下拉框
-                    <template #${javaField}="{ row, column }">
-                      <Select v-model:value="row.${javaField}" class="w-full">
-                        <Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
-                          {{ option.label }}
-                        </Select.Option>
-                      </Select>
-                    </template>
-                  #elseif($column.htmlType == "checkbox")## 多选框
-                    <template #${javaField}="{ row, column }">
-                      <CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
-                    </template>
-                  #elseif($column.htmlType == "radio")## 单选框
-                    <template #${javaField}="{ row, column }">
-                      <RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
-                    </template>
-                  #elseif($column.htmlType == "datetime")## 时间框
-                    <template #${javaField}="{ row }">
-                      <DatePicker
-                          v-model:value="row.${javaField}"
-                          :showTime="true"
-                          format="YYYY-MM-DD HH:mm:ss"
-                          valueFormat='x'
-                      />
-                    </template>
-                  #elseif($column.htmlType == "textarea")## 文本框
-                    <template #${javaField}="{ row }">
-                      <Textarea v-model:value="row.${javaField}" />
-                    </template>
-                  #end
-              #end
-          #end
-      </${subSimpleClassName}Grid>
-      <div class="flex justify-center">
-        <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
-          {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
-        </Button>
-      </div>
-    #else
-      <${subSimpleClassName}Form class="mx-4" />
-    #end
+  <Modal :title="getTitle">
+    <Form class="mx-4" />
+  </Modal>
 </template>

+ 24 - 35
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 '#/api/${table.mo
 #end
 
 const props = defineProps<{
-   ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
+   ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
 }>()
 
 #if ($subTable.subJoinMany) ## 一对多
@@ -41,7 +41,7 @@ function onActionClick({
   }
 }
 
-const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
+const [Grid, gridApi] = useVbenVxeGrid({
 gridOptions: {
   columns: use${subSimpleClassName}GridEditColumns(onActionClick),
   border: true,
@@ -60,34 +60,25 @@ gridOptions: {
 },
 });
 
-/** 删除${subTable.classComment} */
-const onDelete =  async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
-  await ${subClassNameVar}GridApi.grid.remove(row);
+/** 添加${subTable.classComment} */
+const onAdd = async () => {
+  await gridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
 }
 
-/** 添加${subTable.classComment} */
-const handleAdd = async () => {
-  await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
+/** 删除${subTable.classComment} */
+const onDelete =  async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
+  await gridApi.grid.remove(row);
 }
 
 /** 提供获取表格数据的方法供父组件调用 */
 defineExpose({
   getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
-    // 获取当前数据,但排除已删除的记录
-    const allData = ${subClassNameVar}GridApi.grid.getData();
-    const removedData = ${subClassNameVar}GridApi.grid.getRemoveRecords();
-    const removedIds = new Set(removedData.map((row) => row.id));
-
-    // 过滤掉已删除的记录
-    const currentData = allData.filter((row) => !removedIds.has(row.id));
-
-    // 获取新插入的记录并移除id
-    const insertedData = ${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
-      delete row.id;
-      return row;
-    });
-
-    return [...currentData, ...insertedData];
+    const data = gridApi.grid.getData() as ${simpleClassName}Api.${subSimpleClassName}[];
+    const removeRecords = gridApi.grid.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
+    const insertRecords = gridApi.grid.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
+    return data
+        .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
+        .concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
   },
 });
 
@@ -98,14 +89,13 @@ watch(
       if (!val) {
         return;
       }
-
       await nextTick();
-      await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
+      await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
     },
     { immediate: true },
 );
 #else
-const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
+const [Form, formApi] = useVbenForm({
 layout: 'horizontal',
 schema: use${subSimpleClassName}FormSchema(),
 showDefaultActions: false
@@ -114,10 +104,10 @@ showDefaultActions: false
 /** 暴露出表单校验方法和表单值获取方法 */
 defineExpose({
   validate: async () => {
-    const { valid } = await ${subClassNameVar}FormApi.validate();
+    const { valid } = await formApi.validate();
     return valid;
   },
-  getValues: ${subClassNameVar}FormApi.getValues,
+  getValues: formApi.getValues,
 });
 
 /** 监听主表的关联字段的变化,加载对应的子表数据 */
@@ -127,9 +117,8 @@ watch(
       if (!val) {
         return;
       }
-
       await nextTick();
-      await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
+      await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
     },
     { immediate: true },
 );
@@ -138,7 +127,7 @@ watch(
 
 <template>
 #if ($subTable.subJoinMany) ## 一对多
-  <${subSimpleClassName}Grid class="mx-4">
+  <Grid class="mx-4">
       #foreach($column in $subColumns)
           #if ($column.createOperation || $column.updateOperation)
               #set ($javaField = $column.javaField)
@@ -191,13 +180,13 @@ watch(
               #end
           #end
       #end
-  </${subSimpleClassName}Grid>
-  <div class="flex justify-center">
-    <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
+  </Grid>
+  <div class="flex justify-center -mt-4">
+    <Button :icon="h(Plus)" type="primary" ghost @click="onAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
       {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
     </Button>
   </div>
 #else
-  <${subSimpleClassName}Form class="mx-4" />
+  <Form class="mx-4" />
 #end
 </template>

+ 83 - 44
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 @@
 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
-#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
+#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
 <script lang="ts" setup>
   import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
   import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 
+#if ($table.templateType == 11) ## erp
+  import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
+#end
   import { useVbenModal } from '@vben/common-ui';
   import { Button, message } from 'ant-design-vue';
   import { Plus } from '@vben/icons';
-  import { ref, h, nextTick,watch } from 'vue';
+  import { #if($table.templateType != 11)ref,#end h, nextTick,watch } from 'vue';
   import { $t } from '#/locales';
   import { useVbenVxeGrid } from '#/adapter/vxe-table';
 
 
 #if ($table.templateType == 11) ## erp
-  import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
-#end
+  import { delete${subSimpleClassName}, get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
+  import { use${subSimpleClassName}GridFormSchema, use${subSimpleClassName}GridColumns } from '../data';
+  #else
+  #if ($subTable.subJoinMany) ## 一对多
+  import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
+  #else
+  import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
+  #end
   import { use${subSimpleClassName}GridColumns } from '../data';
-#if ($subTable.subJoinMany) ## 一对多
-import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
-#else
-import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 #end
 
 const props = defineProps<{
-      ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
+      ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
 }>()
 
 #if ($table.templateType == 11) ## erp
@@ -39,13 +44,18 @@ const props = defineProps<{
 
 /** 创建${subTable.classComment} */
 function onCreate() {
-  formModalApi.setData({}).open();
+  if (!props.${subJoinColumn.javaField}){
+    message.warning("请先选择一个${table.classComment}!")
+    return
+  }
+  formModalApi.setData({${subJoinColumn.javaField}: props.${subJoinColumn.javaField}}).open();
 }
 
 /** 编辑${subTable.classComment} */
 function onEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
   formModalApi.setData(row).open();
 }
+
 /** 删除${subTable.classComment} */
 async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
   const hideLoading = message.loading({
@@ -71,45 +81,77 @@ function onActionClick({
  row,
 }: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
   switch (code) {
-    case 'delete': {
-      onDelete(row);
-      break;
-    }
     case 'edit': {
       onEdit(row);
       break;
     }
+    case 'delete': {
+      onDelete(row);
+      break;
+    }
   }
 }
+
 #end
   const [Grid, gridApi] = useVbenVxeGrid({
+#if ($table.templateType == 11)
+    formOptions: {
+      schema: use${subSimpleClassName}GridFormSchema(),
+    },
+#end
     gridOptions: {
 #if ($table.templateType == 11)
-      columns: use${subSimpleClassName}GridColumns(onActionClick),
+    columns: use${subSimpleClassName}GridColumns(onActionClick),
+      proxyConfig: {
+        ajax: {
+          query: async ({ page }, formValues) => {
+              if (!props.${subJoinColumn.javaField}){
+                  return []
+              }
+            return await get${subSimpleClassName}Page({
+              pageNo: page.currentPage,
+              pageSize: page.pageSize,
+              ${subJoinColumn.javaField}: props.${subJoinColumn.javaField},
+              ...formValues,
+            });
+          },
+        },
+      },
+    pagerConfig: {
+        enabled: true,
+    },
+    toolbarConfig: {
+        refresh: { code: 'query' },
+        search: true,
+    },
 #else
-      columns: use${subSimpleClassName}GridColumns(),
+    columns: use${subSimpleClassName}GridColumns(),
+    pagerConfig: {
+        enabled: false,
+    },
+    toolbarConfig: {
+        enabled: false,
+    },
 #end
-      height: 'auto',
-      rowConfig: {
+    height: '600px',
+    rowConfig: {
         keyField: 'id',
         isHover: true,
-      },
-      pagerConfig: {
-        enabled: false,
-      },
-      toolbarConfig: {
-        enabled: false,
-      },
-    } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
+    },
+    } as VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>,
   });
 
 /** 刷新表格 */
 const onRefresh = async ()=> {
-  #if ($subTable.subJoinMany) ## 一对多
+#if ($table.templateType == 11) ## erp
+    await gridApi.query();
+#else
+    #if ($subTable.subJoinMany) ## 一对多
     await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
-  #else
+    #else
     await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
-  #end
+    #end
+#end
 }
 
   /** 监听主表的关联字段的变化,加载对应的子表数据 */
@@ -119,7 +161,6 @@ const onRefresh = async ()=> {
         if (!val) {
           return;
         }
-
         await nextTick();
         await onRefresh()
       },
@@ -128,18 +169,16 @@ const onRefresh = async ()=> {
 </script>
 
 <template>
-    <div class="mx-4">
-        #if ($table.templateType == 11) ## erp
-          <FormModal @success="onRefresh" />
-          <Grid table-title="${subTable.classComment}列表">
-            <template #toolbar-tools>
-              <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${subTable.moduleName}:${subSimpleClassName_strikeCase}:create']">
-                {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
-              </Button>
-            </template>
-          </Grid>
-        #else
-        <Grid table-title="${subTable.classComment}列表" />
-        #end
-    </div>
+    #if ($table.templateType == 11) ## erp
+      <FormModal @success="onRefresh" />
+      <Grid table-title="${subTable.classComment}列表">
+        <template #toolbar-tools>
+          <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:create']">
+            {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
+          </Button>
+        </template>
+      </Grid>
+    #else
+      <Grid table-title="${subTable.classComment}列表" />
+    #end
 </template>