Kaynağa Gözat

【代码优化】代码生成: vue3_vben5_antd schema 主子表标准模式和内嵌模式模板完成

puhui999 6 ay önce
ebeveyn
işleme
e1fa4e1a70

+ 36 - 20
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm

@@ -202,6 +202,9 @@ export function useGridColumns(
   onActionClick?: OnActionClickFn<${simpleClassName}Api.${simpleClassName}>,
 ): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
   return [
+#if ($table.templateType == 12) ## 内嵌情况
+      { type: 'expand', width: 80, slots: { content: 'expand_content' } },
+#end
 #foreach($column in $columns)
 #if ($column.listOperationResult)
   #set ($dictType = $column.dictType)
@@ -274,6 +277,7 @@ export function useGridColumns(
     #set ($subColumns = $subColumnsList.get($index))##当前字段数组
     #set ($subSimpleClassName = $subSimpleClassNames.get($index))
     #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
+    #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
 // ==================== 子表($subTable.classComment) ====================
 #if ($table.templateType == 11) ## erp 情况
 /** 新增/修改的表单 */
@@ -409,9 +413,6 @@ export function use${subSimpleClassName}GridColumns(
                             props: { type: DICT_TYPE.$dictType.toUpperCase() },
                         },
                     #end
-                    #if (${table.templateType} == 2 && $column.id == $treeNameColumn.id)## 树表特有:标记树节点列
-                        treeNode: true,
-                    #end
                 },
             #end
         #end
@@ -426,30 +427,18 @@ export function use${subSimpleClassName}GridColumns(
             cellRender: {
                 attrs: {
                     nameField: '${columns[0].javaField}',
-                    nameTitle: '${table.classComment}',
+                    nameTitle: '${subTable.classComment}',
                     onClick: onActionClick,
                 },
                 name: 'CellOperation',
                 options: [
-                    #if (${table.templateType} == 2)## 树表特有操作
-                        {
-                            code: 'append',
-                            text: '新增下级',
-                            show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:create']),
-                        },
-                    #end
                     {
                         code: 'edit',
-                        show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']),
+                        show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:update']),
                     },
                     {
                         code: 'delete',
-                        show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
-                        #if (${table.templateType} == 2)## 树表禁止删除带有子节点的数据
-                            disabled: (row: ${simpleClassName}Api.${simpleClassName}) => {
-                                return !!(row.children && row.children.length > 0);
-                            },
-                        #end
+                        show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:delete']),
                     },
                 ],
             },
@@ -458,8 +447,8 @@ export function use${subSimpleClassName}GridColumns(
 }
 #else
     #if ($subTable.subJoinMany) ## 一对多
-    /** 列表的字段 */
-    export function use${subSimpleClassName}GridColumns(
+    /** 新增/修改列表的字段 */
+    export function use${subSimpleClassName}GridEditColumns(
         onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
     ): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
         return [
@@ -634,5 +623,32 @@ export function use${subSimpleClassName}GridColumns(
         ];
     }
     #end
+    #if ($table.templateType == 12) ## 内嵌情况
+    /** 列表的字段 */
+    export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
+        return [
+            #foreach($column in $subColumns)
+                #if ($column.listOperationResult)
+                    #set ($dictType = $column.dictType)
+                    #set ($javaField = $column.javaField)
+                    #set ($comment = $column.columnComment)
+                    {
+                        field: '${javaField}',
+                        title: '${comment}',
+                        minWidth: 120,
+                        #if ($column.javaType == "LocalDateTime")## 时间类型
+                            formatter: 'formatDateTime',
+                        #elseif("" != $dictType)## 数据字典
+                            cellRender: {
+                                name: 'CellDict',
+                                props: { type: DICT_TYPE.$dictType.toUpperCase() },
+                            },
+                        #end
+                    },
+                #end
+            #end
+        ];
+    }
+    #end
 #end
 #end

+ 1 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/form.vue.vm

@@ -116,6 +116,7 @@ const [Modal, modalApi] = useVbenModal({
   },
   async onOpenChange(isOpen: boolean) {
     if (!isOpen) {
+      formData.value = undefined;
       return;
     }
 

+ 34 - 2
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm

@@ -3,10 +3,17 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-tab
 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 
 import { Page, useVbenModal } from '@vben/common-ui';
-import { Button, message } from 'ant-design-vue';
+import { Button, message,Tabs } from 'ant-design-vue';
 import { Download, Plus } from '@vben/icons';
 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'
+    #end
+#end
+
 import { ref, h } from 'vue';
 import { $t } from '#/locales';
 import { useVbenVxeGrid } from '#/adapter/vxe-table';
@@ -19,6 +26,11 @@ import { downloadByData } from '#/utils/download';
 
 import { useGridColumns, useGridFormSchema } from './data';
 
+#if ($table.templateType == 12) ## 内嵌情况
+/** 子表的列表 */
+const subTabsName = ref('$subClassNameVars.get(0)')
+#end
+
 const [FormModal, formModalApi] = useVbenModal({
   connectedComponent: Form,
   destroyOnClose: true,
@@ -35,7 +47,11 @@ function toggleExpand() {
 
 /** 刷新表格 */
 function onRefresh() {
+#if ($table.templateType == 12) ## 内嵌情况
+  gridApi.reload();
+#else
   gridApi.query();
+#end
 }
 
 /** 导出表格 */
@@ -46,7 +62,7 @@ async function onExport() {
 
 /** 创建${table.classComment} */
 function onCreate() {
-  formModalApi.setData(null).open();
+  formModalApi.setData({}).open();
 }
 
 /** 编辑${table.classComment} */
@@ -160,6 +176,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
     <FormModal @success="onRefresh" />
 
     <Grid table-title="${table.classComment}列表">
+        #if ($table.templateType == 12) ## 内嵌情况
+          <template #expand_content="{ row }">
+            <!-- 子表的表单 -->
+            <Tabs v-model:active-key="subTabsName">
+                #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}="row?.id" />
+                  </Tabs.TabPane>
+                #end
+            </Tabs>
+          </template>
+        #end
       <template #toolbar-tools>
 #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
         <Button @click="toggleExpand" class="mr-2">

+ 181 - 192
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_erp.vue.vm

@@ -1,204 +1,193 @@
+#set ($subTable = $subTables.get($subIndex))##当前表
 #set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
-#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-#foreach($column in $subColumns)
-    #if ($column.createOperation || $column.updateOperation)
-        #set ($dictType = $column.dictType)
-        #set ($javaField = $column.javaField)
-        #set ($javaType = $column.javaType)
-        #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
-        #set ($comment = $column.columnComment)
-        #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
-        #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
-            #set ($dictMethod = "getIntDictOptions")
-        #elseif ($javaType == "String")
-            #set ($dictMethod = "getStrDictOptions")
-        #elseif ($javaType == "Boolean")
-            #set ($dictMethod = "getBoolDictOptions")
-        #end
-        #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
-        #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
-      <el-form-item label="${comment}" prop="${javaField}">
-        <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
-      </el-form-item>
-        #elseif($column.htmlType == "imageUpload")## 图片上传
-      <el-form-item label="${comment}" prop="${javaField}">
-        <UploadImg v-model="formData.${javaField}" />
-      </el-form-item>
-        #elseif($column.htmlType == "fileUpload")## 文件上传
-      <el-form-item label="${comment}" prop="${javaField}">
-        <UploadFile v-model="formData.${javaField}" />
-      </el-form-item>
-        #elseif($column.htmlType == "editor")## 文本编辑器
-      <el-form-item label="${comment}" prop="${javaField}">
-        <Editor v-model="formData.${javaField}" height="150px" />
-      </el-form-item>
-        #elseif($column.htmlType == "select")## 下拉框
-      <el-form-item label="${comment}" prop="${javaField}">
-        <el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
-                #if ("" != $dictType)## 有数据字典
-          <el-option
-            v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-                #else##没数据字典
-          <el-option label="请选择字典生成" value="" />
-                #end
-        </el-select>
-      </el-form-item>
-        #elseif($column.htmlType == "checkbox")## 多选框
-      <el-form-item label="${comment}" prop="${javaField}">
-        <el-checkbox-group v-model="formData.${javaField}">
-                #if ("" != $dictType)## 有数据字典
-          <el-checkbox
-            v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-                #else##没数据字典
-          <el-checkbox label="请选择字典生成" />
-                #end
-        </el-checkbox-group>
-      </el-form-item>
-        #elseif($column.htmlType == "radio")## 单选框
-      <el-form-item label="${comment}" prop="${javaField}">
-        <el-radio-group v-model="formData.${javaField}">
-                #if ("" != $dictType)## 有数据字典
-          <el-radio
-            v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
-            :key="dict.value"
-            :label="dict.value"
-          >
-            {{ dict.label }}
-          </el-radio>
-                #else##没数据字典
-          <el-radio value="1">请选择字典生成</el-radio>
-                #end
-        </el-radio-group>
-      </el-form-item>
-        #elseif($column.htmlType == "datetime")## 时间框
-      <el-form-item label="${comment}" prop="${javaField}">
-        <el-date-picker
-          v-model="formData.${javaField}"
-          type="date"
-          value-format="x"
-          placeholder="选择${comment}"
-        />
-      </el-form-item>
-        #elseif($column.htmlType == "textarea")## 文本框
-      <el-form-item label="${comment}" prop="${javaField}">
-        <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
-      </el-form-item>
-        #end
-    #end
-#end
-    </el-form>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
+#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}';
 
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
+  import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
+  import { $t } from '#/locales';
 
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-#foreach ($column in $subColumns)
-    #if ($column.createOperation || $column.updateOperation)
-      #if ($column.htmlType == "checkbox")
-  $column.javaField: [],
-      #else
-  $column.javaField: undefined,
-      #end
-    #end
+#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 formRules = reactive({
-#foreach ($column in $subColumns)
-    #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
-        #set($comment=$column.columnComment)
-  $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
-    #end
-#end
-})
-const formRef = ref() // 表单 Ref
 
-/** 打开弹窗 */
-const open = async (type: string, id?: number, ${subJoinColumn.javaField}: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  formData.value.${subJoinColumn.javaField} = ${subJoinColumn.javaField}
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await ${simpleClassName}Api.get${subSimpleClassName}(id)
-    } finally {
-      formLoading.value = false
-    }
+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;
   }
 }
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+}
 
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value
-    if (formType.value === 'create') {
-      await ${simpleClassName}Api.create${subSimpleClassName}(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await ${simpleClassName}Api.update${subSimpleClassName}(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
+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);
 }
 
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-#foreach ($column in $subColumns)
-  #if ($column.createOperation || $column.updateOperation)
-      #if ($column.htmlType == "checkbox")
-    $column.javaField: [],
-      #else
-    $column.javaField: undefined,
-      #end
-  #end
-#end
-  }
-  formRef.value?.resetFields()
+/** 添加${subTable.classComment} */
+const handleAdd = async () => {
+await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
 }
-</script>
+
+/** 提供获取表格数据的方法供父组件调用 */
+defineExpose({
+getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
+  return [
+    ...${subClassNameVar}GridApi.grid.getData(),
+    ...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
+      delete row.id;
+      return row;
+    }),
+  ];
+},
+});
+
+/** 监听主表的关联字段的变化,加载对应的子表数据 */
+watch(
+  () => props.${subJoinColumn.javaField},
+  async (val) => {
+    if (!val) {
+      return;
+    }
+
+    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
+});
+
+/** 暴露出表单校验方法和表单值获取方法 */
+defineExpose({
+validate: async () => {
+  const { valid } = await ${subClassNameVar}FormApi.validate();
+  return valid;
+},
+getValues: ${subClassNameVar}FormApi.getValues,
+});
+
+/** 监听主表的关联字段的变化,加载对应的子表数据 */
+watch(
+  () => props.${subJoinColumn.javaField},
+  async (val) => {
+    if (!val) {
+      return;
+    }
+
+    await nextTick();
+    await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
+  },
+);
+#end
+</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
+</template>

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_inner.vue.vm

@@ -1,2 +1,2 @@
 ## 主表的 normal 和 inner 使用相同的 form 表单
-#parse("codegen/vue3/views/components/form_sub_normal.vue.vm")
+#parse("codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm")

+ 19 - 9
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm

@@ -15,7 +15,7 @@ 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 { use${subSimpleClassName}GridEditColumns } from '../data';
 import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 #else
 import { useVbenForm } from '#/adapter/form';
@@ -43,7 +43,7 @@ function onActionClick({
 
 const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
 gridOptions: {
-  columns: use${subSimpleClassName}GridColumns(onActionClick),
+  columns: use${subSimpleClassName}GridEditColumns(onActionClick),
   border: true,
   showOverflow: true,
   autoResize: true,
@@ -73,13 +73,21 @@ const handleAdd = async () => {
 /** 提供获取表格数据的方法供父组件调用 */
 defineExpose({
   getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
-    return [
-      ...${subClassNameVar}GridApi.grid.getData(),
-      ...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
-        delete row.id;
-        return row;
-      }),
-    ];
+    // 获取当前数据,但排除已删除的记录
+    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];
   },
 });
 
@@ -94,6 +102,7 @@ watch(
       await nextTick();
       await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
     },
+    { immediate: true },
 );
 #else
 const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
@@ -122,6 +131,7 @@ watch(
       await nextTick();
       await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
     },
+    { immediate: true },
 );
 #end
 </script>

+ 122 - 161
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm

@@ -3,182 +3,143 @@
 #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 ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
-<template>
-  <!-- 列表 -->
-  <ContentWrap>
-#if ($table.templateType == 11)
-    <el-button
-      type="primary"
-      plain
-      @click="openForm('create')"
-      v-hasPermi="['${permissionPrefix}:create']"
-    >
-      <Icon icon="ep:plus" class="mr-5px" /> 新增
-    </el-button>
-#end
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      #foreach($column in $subColumns)
-      #if ($column.listOperationResult)
-        #set ($dictType=$column.dictType)
-        #set ($javaField = $column.javaField)
-        #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
-        #set ($comment=$column.columnComment)
-        #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
-        #elseif ($column.javaType == "LocalDateTime")## 时间类型
-      <el-table-column
-        label="${comment}"
-        align="center"
-        prop="${javaField}"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-        #elseif($column.dictType && "" != $column.dictType)## 数据字典
-      <el-table-column label="${comment}" align="center" prop="${javaField}">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
-        </template>
-      </el-table-column>
-        #else
-      <el-table-column label="${comment}" align="center" prop="${javaField}" />
-        #end
-      #end
-    #end
-    #if ($table.templateType == 11)
-      <el-table-column label="操作" align="center">
-        <template #default="scope">
-          <el-button
-            link
-            type="primary"
-            @click="openForm('update', scope.row.id)"
-            v-hasPermi="['${permissionPrefix}:update']"
-          >
-            编辑
-          </el-button>
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-            v-hasPermi="['${permissionPrefix}:delete']"
-          >
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    #end
-    </el-table>
-    #if ($table.templateType == 11)
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-    #end
-  </ContentWrap>
-#if ($table.templateType == 11)
-    <!-- 表单弹窗:添加/修改 -->
-    <${subSimpleClassName}Form ref="formRef" @success="getList" />
+<script lang="ts" setup>
+  import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
+  import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
+
+  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 { $t } from '#/locales';
+  import { useVbenVxeGrid } from '#/adapter/vxe-table';
+
+
+#if ($table.templateType == 11) ## erp
+  import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
 #end
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import { dateFormatter } from '@/utils/formatTime'
-import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
-#if ($table.templateType == 11)
-import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
+  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 { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
 const props = defineProps<{
-  ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
+      ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
 }>()
-const loading = ref(false) // 列表的加载中
-const list = ref([]) // 列表的数据
-#if ($table.templateType == 11)
-const total = ref(0) // 列表的总页数
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  ${subJoinColumn.javaField}: undefined as unknown
-})
 
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.${subJoinColumn.javaField},
-  (val: number) => {
-    if (!val) {
-      return
-    }
-    queryParams.${subJoinColumn.javaField} = val
-    handleQuery()
-  },
-    { immediate: true, deep: true }
-)
-#end
+#if ($table.templateType == 11) ## erp
+  const [FormModal, formModalApi] = useVbenModal({
+    connectedComponent: ${subSimpleClassName}Form,
+    destroyOnClose: true,
+  });
+
+/** 创建${subTable.classComment} */
+function onCreate() {
+  formModalApi.setData({}).open();
+}
 
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
+/** 编辑${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({
+    content: $t('ui.actionMessage.deleting', [row.id]),
+    duration: 0,
+    key: 'action_process_msg',
+  });
   try {
-#if ($table.templateType == 11)
-    const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
-    list.value = data.list
-    total.value = data.total
-#else
-  #if ( $subTable.subJoinMany )
-    list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
-  #else
-    const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
-    if (!data) {
-      return
-    }
-    list.value.push(data)
-  #end
-#end
-  } finally {
-    loading.value = false
+    await delete${subSimpleClassName}(row.id as number);
+    message.success({
+      content: $t('ui.actionMessage.deleteSuccess', [row.id]),
+      key: 'action_process_msg',
+    });
+    onRefresh();
+  } catch {
+    hideLoading();
   }
 }
 
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
+/** 表格操作按钮的回调函数 */
+function onActionClick({
+ code,
+ row,
+}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
+  switch (code) {
+    case 'delete': {
+      onDelete(row);
+      break;
+    }
+    case 'edit': {
+      onEdit(row);
+      break;
+    }
+  }
 }
+#end
+  const [Grid, gridApi] = useVbenVxeGrid({
+    gridOptions: {
 #if ($table.templateType == 11)
+      columns: use${subSimpleClassName}GridColumns(onActionClick),
+#else
+      columns: use${subSimpleClassName}GridColumns(),
+#end
+      height: 'auto',
+      rowConfig: {
+        keyField: 'id',
+        isHover: true,
+      },
+      pagerConfig: {
+        enabled: false,
+      },
+      toolbarConfig: {
+        enabled: false,
+      },
+    } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
+  });
 
-/** 添加/修改操作 */
-const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  if (!props.${subJoinColumn.javaField}) {
-    message.error('请选择一个${table.classComment}')
-    return
-  }
-  formRef.value.open(type, id, props.${subJoinColumn.javaField})
+/** 刷新表格 */
+const onRefresh = async ()=> {
+  #if ($subTable.subJoinMany) ## 一对多
+    await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
+  #else
+    await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
+  #end
 }
 
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await ${simpleClassName}Api.delete${subSimpleClassName}(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {}
-}
-#end
-#if ($table.templateType != 11)
+  /** 监听主表的关联字段的变化,加载对应的子表数据 */
+  watch(
+      () => props.${subJoinColumn.javaField},
+      async (val) => {
+        if (!val) {
+          return;
+        }
 
-/** 初始化 **/
-onMounted(() => {
-  getList()
-})
-#end
-</script>
+        await nextTick();
+        await onRefresh()
+      },
+      { immediate: true },
+  );
+</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>
+</template>

+ 1 - 1
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_inner.vue.vm

@@ -1,4 +1,4 @@
 ## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
 ## 1)inner 使用 list 不分页,erp 使用 page 分页
 ## 2)erp 支持单个子表的新增、修改、删除,inner 不支持
-#parse("codegen/vue3/views/components/list_sub_erp.vue.vm")
+#parse("codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm")