Commit e1fa4e1a70d2f87e6b86832ac63eb7150d728a82

Authored by puhui999
1 parent dfcbcf09

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

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(
202 202 onActionClick?: OnActionClickFn<${simpleClassName}Api.${simpleClassName}>,
203 203 ): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
204 204 return [
  205 +#if ($table.templateType == 12) ## 内嵌情况
  206 + { type: 'expand', width: 80, slots: { content: 'expand_content' } },
  207 +#end
205 208 #foreach($column in $columns)
206 209 #if ($column.listOperationResult)
207 210 #set ($dictType = $column.dictType)
... ... @@ -274,6 +277,7 @@ export function useGridColumns(
274 277 #set ($subColumns = $subColumnsList.get($index))##当前字段数组
275 278 #set ($subSimpleClassName = $subSimpleClassNames.get($index))
276 279 #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
  280 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
277 281 // ==================== 子表($subTable.classComment) ====================
278 282 #if ($table.templateType == 11) ## erp 情况
279 283 /** 新增/修改的表单 */
... ... @@ -409,9 +413,6 @@ export function use${subSimpleClassName}GridColumns(
409 413 props: { type: DICT_TYPE.$dictType.toUpperCase() },
410 414 },
411 415 #end
412   - #if (${table.templateType} == 2 && $column.id == $treeNameColumn.id)## 树表特有:标记树节点列
413   - treeNode: true,
414   - #end
415 416 },
416 417 #end
417 418 #end
... ... @@ -426,30 +427,18 @@ export function use${subSimpleClassName}GridColumns(
426 427 cellRender: {
427 428 attrs: {
428 429 nameField: '${columns[0].javaField}',
429   - nameTitle: '${table.classComment}',
  430 + nameTitle: '${subTable.classComment}',
430 431 onClick: onActionClick,
431 432 },
432 433 name: 'CellOperation',
433 434 options: [
434   - #if (${table.templateType} == 2)## 树表特有操作
435   - {
436   - code: 'append',
437   - text: '新增下级',
438   - show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:create']),
439   - },
440   - #end
441 435 {
442 436 code: 'edit',
443   - show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']),
  437 + show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:update']),
444 438 },
445 439 {
446 440 code: 'delete',
447   - show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
448   - #if (${table.templateType} == 2)## 树表禁止删除带有子节点的数据
449   - disabled: (row: ${simpleClassName}Api.${simpleClassName}) => {
450   - return !!(row.children && row.children.length > 0);
451   - },
452   - #end
  441 + show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:delete']),
453 442 },
454 443 ],
455 444 },
... ... @@ -458,8 +447,8 @@ export function use${subSimpleClassName}GridColumns(
458 447 }
459 448 #else
460 449 #if ($subTable.subJoinMany) ## 一对多
461   - /** 列表的字段 */
462   - export function use${subSimpleClassName}GridColumns(
  450 + /** 新增/修改列表的字段 */
  451 + export function use${subSimpleClassName}GridEditColumns(
463 452 onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
464 453 ): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
465 454 return [
... ... @@ -634,5 +623,32 @@ export function use${subSimpleClassName}GridColumns(
634 623 ];
635 624 }
636 625 #end
  626 + #if ($table.templateType == 12) ## 内嵌情况
  627 + /** 列表的字段 */
  628 + export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  629 + return [
  630 + #foreach($column in $subColumns)
  631 + #if ($column.listOperationResult)
  632 + #set ($dictType = $column.dictType)
  633 + #set ($javaField = $column.javaField)
  634 + #set ($comment = $column.columnComment)
  635 + {
  636 + field: '${javaField}',
  637 + title: '${comment}',
  638 + minWidth: 120,
  639 + #if ($column.javaType == "LocalDateTime")## 时间类型
  640 + formatter: 'formatDateTime',
  641 + #elseif("" != $dictType)## 数据字典
  642 + cellRender: {
  643 + name: 'CellDict',
  644 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  645 + },
  646 + #end
  647 + },
  648 + #end
  649 + #end
  650 + ];
  651 + }
  652 + #end
637 653 #end
638 654 #end
639 655 \ 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
... ... @@ -116,6 +116,7 @@ const [Modal, modalApi] = useVbenModal({
116 116 },
117 117 async onOpenChange(isOpen: boolean) {
118 118 if (!isOpen) {
  119 + formData.value = undefined;
119 120 return;
120 121 }
121 122  
... ...
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 &#39;#/adapter/vxe-tab
3 3 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
4 4  
5 5 import { Page, useVbenModal } from '@vben/common-ui';
6   -import { Button, message } from 'ant-design-vue';
  6 +import { Button, message,Tabs } from 'ant-design-vue';
7 7 import { Download, Plus } from '@vben/icons';
8 8 import Form from './modules/form.vue';
9 9  
  10 +## 特殊:主子表专属逻辑
  11 +#if ( $table.templateType == 11 || $table.templateType == 12 )
  12 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  13 + import ${subSimpleClassName}List from './modules/${subSimpleClassName}List.vue'
  14 + #end
  15 +#end
  16 +
10 17 import { ref, h } from 'vue';
11 18 import { $t } from '#/locales';
12 19 import { useVbenVxeGrid } from '#/adapter/vxe-table';
... ... @@ -19,6 +26,11 @@ import { downloadByData } from &#39;#/utils/download&#39;;
19 26  
20 27 import { useGridColumns, useGridFormSchema } from './data';
21 28  
  29 +#if ($table.templateType == 12) ## 内嵌情况
  30 +/** 子表的列表 */
  31 +const subTabsName = ref('$subClassNameVars.get(0)')
  32 +#end
  33 +
22 34 const [FormModal, formModalApi] = useVbenModal({
23 35 connectedComponent: Form,
24 36 destroyOnClose: true,
... ... @@ -35,7 +47,11 @@ function toggleExpand() {
35 47  
36 48 /** 刷新表格 */
37 49 function onRefresh() {
  50 +#if ($table.templateType == 12) ## 内嵌情况
  51 + gridApi.reload();
  52 +#else
38 53 gridApi.query();
  54 +#end
39 55 }
40 56  
41 57 /** 导出表格 */
... ... @@ -46,7 +62,7 @@ async function onExport() {
46 62  
47 63 /** 创建${table.classComment} */
48 64 function onCreate() {
49   - formModalApi.setData(null).open();
  65 + formModalApi.setData({}).open();
50 66 }
51 67  
52 68 /** 编辑${table.classComment} */
... ... @@ -160,6 +176,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
160 176 <FormModal @success="onRefresh" />
161 177  
162 178 <Grid table-title="${table.classComment}列表">
  179 + #if ($table.templateType == 12) ## 内嵌情况
  180 + <template #expand_content="{ row }">
  181 + <!-- 子表的表单 -->
  182 + <Tabs v-model:active-key="subTabsName">
  183 + #foreach ($subTable in $subTables)
  184 + #set ($index = $foreach.count - 1)
  185 + #set ($subClassNameVar = $subClassNameVars.get($index))
  186 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  187 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  188 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  189 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" />
  190 + </Tabs.TabPane>
  191 + #end
  192 + </Tabs>
  193 + </template>
  194 + #end
163 195 <template #toolbar-tools>
164 196 #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
165 197 <Button @click="toggleExpand" class="mr-2">
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_erp.vue.vm
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
1 2 #set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
2   -#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
3 3 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
4   -<template>
5   - <Dialog :title="dialogTitle" v-model="dialogVisible">
6   - <el-form
7   - ref="formRef"
8   - :model="formData"
9   - :rules="formRules"
10   - label-width="100px"
11   - v-loading="formLoading"
12   - >
13   -#foreach($column in $subColumns)
14   - #if ($column.createOperation || $column.updateOperation)
15   - #set ($dictType = $column.dictType)
16   - #set ($javaField = $column.javaField)
17   - #set ($javaType = $column.javaType)
18   - #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
19   - #set ($comment = $column.columnComment)
20   - #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
21   - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
22   - #set ($dictMethod = "getIntDictOptions")
23   - #elseif ($javaType == "String")
24   - #set ($dictMethod = "getStrDictOptions")
25   - #elseif ($javaType == "Boolean")
26   - #set ($dictMethod = "getBoolDictOptions")
27   - #end
28   - #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
29   - #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
30   - <el-form-item label="${comment}" prop="${javaField}">
31   - <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
32   - </el-form-item>
33   - #elseif($column.htmlType == "imageUpload")## 图片上传
34   - <el-form-item label="${comment}" prop="${javaField}">
35   - <UploadImg v-model="formData.${javaField}" />
36   - </el-form-item>
37   - #elseif($column.htmlType == "fileUpload")## 文件上传
38   - <el-form-item label="${comment}" prop="${javaField}">
39   - <UploadFile v-model="formData.${javaField}" />
40   - </el-form-item>
41   - #elseif($column.htmlType == "editor")## 文本编辑器
42   - <el-form-item label="${comment}" prop="${javaField}">
43   - <Editor v-model="formData.${javaField}" height="150px" />
44   - </el-form-item>
45   - #elseif($column.htmlType == "select")## 下拉框
46   - <el-form-item label="${comment}" prop="${javaField}">
47   - <el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
48   - #if ("" != $dictType)## 有数据字典
49   - <el-option
50   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
51   - :key="dict.value"
52   - :label="dict.label"
53   - :value="dict.value"
54   - />
55   - #else##没数据字典
56   - <el-option label="请选择字典生成" value="" />
57   - #end
58   - </el-select>
59   - </el-form-item>
60   - #elseif($column.htmlType == "checkbox")## 多选框
61   - <el-form-item label="${comment}" prop="${javaField}">
62   - <el-checkbox-group v-model="formData.${javaField}">
63   - #if ("" != $dictType)## 有数据字典
64   - <el-checkbox
65   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
66   - :key="dict.value"
67   - :label="dict.label"
68   - :value="dict.value"
69   - />
70   - #else##没数据字典
71   - <el-checkbox label="请选择字典生成" />
72   - #end
73   - </el-checkbox-group>
74   - </el-form-item>
75   - #elseif($column.htmlType == "radio")## 单选框
76   - <el-form-item label="${comment}" prop="${javaField}">
77   - <el-radio-group v-model="formData.${javaField}">
78   - #if ("" != $dictType)## 有数据字典
79   - <el-radio
80   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
81   - :key="dict.value"
82   - :label="dict.value"
83   - >
84   - {{ dict.label }}
85   - </el-radio>
86   - #else##没数据字典
87   - <el-radio value="1">请选择字典生成</el-radio>
88   - #end
89   - </el-radio-group>
90   - </el-form-item>
91   - #elseif($column.htmlType == "datetime")## 时间框
92   - <el-form-item label="${comment}" prop="${javaField}">
93   - <el-date-picker
94   - v-model="formData.${javaField}"
95   - type="date"
96   - value-format="x"
97   - placeholder="选择${comment}"
98   - />
99   - </el-form-item>
100   - #elseif($column.htmlType == "textarea")## 文本框
101   - <el-form-item label="${comment}" prop="${javaField}">
102   - <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
103   - </el-form-item>
104   - #end
105   - #end
106   -#end
107   - </el-form>
108   - <template #footer>
109   - <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
110   - <el-button @click="dialogVisible = false">取 消</el-button>
111   - </template>
112   - </Dialog>
113   -</template>
114   -<script setup lang="ts">
115   -import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
116   -import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
  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 +<script lang="ts" setup>
  8 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
117 9  
118   -const { t } = useI18n() // 国际化
119   -const message = useMessage() // 消息弹窗
  10 + import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  11 + import { $t } from '#/locales';
120 12  
121   -const dialogVisible = ref(false) // 弹窗的是否展示
122   -const dialogTitle = ref('') // 弹窗的标题
123   -const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
124   -const formType = ref('') // 表单的类型:create - 新增;update - 修改
125   -const formData = ref({
126   -#foreach ($column in $subColumns)
127   - #if ($column.createOperation || $column.updateOperation)
128   - #if ($column.htmlType == "checkbox")
129   - $column.javaField: [],
130   - #else
131   - $column.javaField: undefined,
132   - #end
133   - #end
  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}';
134 24 #end
135   -})
136   -const formRules = reactive({
137   -#foreach ($column in $subColumns)
138   - #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
139   - #set($comment=$column.columnComment)
140   - $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
141   - #end
142   -#end
143   -})
144   -const formRef = ref() // 表单 Ref
145 25  
146   -/** 打开弹窗 */
147   -const open = async (type: string, id?: number, ${subJoinColumn.javaField}: number) => {
148   - dialogVisible.value = true
149   - dialogTitle.value = t('action.' + type)
150   - formType.value = type
151   - resetForm()
152   - formData.value.${subJoinColumn.javaField} = ${subJoinColumn.javaField}
153   - // 修改时,设置数据
154   - if (id) {
155   - formLoading.value = true
156   - try {
157   - formData.value = await ${simpleClassName}Api.get${subSimpleClassName}(id)
158   - } finally {
159   - formLoading.value = false
160   - }
  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;
161 40 }
162 41 }
163   -defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  42 +}
164 43  
165   -/** 提交表单 */
166   -const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
167   -const submitForm = async () => {
168   - // 校验表单
169   - await formRef.value.validate()
170   - // 提交请求
171   - formLoading.value = true
172   - try {
173   - const data = formData.value
174   - if (formType.value === 'create') {
175   - await ${simpleClassName}Api.create${subSimpleClassName}(data)
176   - message.success(t('common.createSuccess'))
177   - } else {
178   - await ${simpleClassName}Api.update${subSimpleClassName}(data)
179   - message.success(t('common.updateSuccess'))
180   - }
181   - dialogVisible.value = false
182   - // 发送操作成功的事件
183   - emit('success')
184   - } finally {
185   - formLoading.value = false
186   - }
  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);
187 66 }
188 67  
189   -/** 重置表单 */
190   -const resetForm = () => {
191   - formData.value = {
192   -#foreach ($column in $subColumns)
193   - #if ($column.createOperation || $column.updateOperation)
194   - #if ($column.htmlType == "checkbox")
195   - $column.javaField: [],
196   - #else
197   - $column.javaField: undefined,
198   - #end
199   - #end
200   -#end
201   - }
202   - formRef.value?.resetFields()
  68 +/** 添加${subTable.classComment} */
  69 +const handleAdd = async () => {
  70 +await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
203 71 }
204   -</script>
205 72 \ No newline at end of file
  73 +
  74 +/** 提供获取表格数据的方法供父组件调用 */
  75 +defineExpose({
  76 +getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
  77 + return [
  78 + ...${subClassNameVar}GridApi.grid.getData(),
  79 + ...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
  80 + delete row.id;
  81 + return row;
  82 + }),
  83 + ];
  84 +},
  85 +});
  86 +
  87 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  88 +watch(
  89 + () => props.${subJoinColumn.javaField},
  90 + async (val) => {
  91 + if (!val) {
  92 + return;
  93 + }
  94 +
  95 + await nextTick();
  96 + await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  97 + },
  98 +);
  99 +#else
  100 +const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
  101 +layout: 'horizontal',
  102 +schema: use${subSimpleClassName}FormSchema(),
  103 +showDefaultActions: false
  104 +});
  105 +
  106 +/** 暴露出表单校验方法和表单值获取方法 */
  107 +defineExpose({
  108 +validate: async () => {
  109 + const { valid } = await ${subClassNameVar}FormApi.validate();
  110 + return valid;
  111 +},
  112 +getValues: ${subClassNameVar}FormApi.getValues,
  113 +});
  114 +
  115 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  116 +watch(
  117 + () => props.${subJoinColumn.javaField},
  118 + async (val) => {
  119 + if (!val) {
  120 + return;
  121 + }
  122 +
  123 + await nextTick();
  124 + await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  125 + },
  126 +);
  127 +#end
  128 +</script>
  129 +
  130 +<template>
  131 + #if ($subTable.subJoinMany) ## 一对多
  132 + <${subSimpleClassName}Grid class="mx-4">
  133 + #foreach($column in $subColumns)
  134 + #if ($column.createOperation || $column.updateOperation)
  135 + #set ($javaField = $column.javaField)
  136 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  137 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  138 + <template #${javaField}="{ row }">
  139 + <Input v-model:value="row.${javaField}" />
  140 + </template>
  141 + #elseif($column.htmlType == "imageUpload")## 图片上传
  142 + <template #${javaField}="{ row }">
  143 + <UploadImg v-model:value="row.${javaField}" />
  144 + </template>
  145 + #elseif($column.htmlType == "fileUpload")## 文件上传
  146 + <template #${javaField}="{ row }">
  147 + <UploadFile v-model:value="row.${javaField}" />
  148 + </template>
  149 + #elseif($column.htmlType == "editor")## 文本编辑器
  150 + <template #${javaField}="{ row }">
  151 + <Textarea v-model:value="row.${javaField}" />
  152 + </template>
  153 + #elseif($column.htmlType == "select")## 下拉框
  154 + <template #${javaField}="{ row, column }">
  155 + <Select v-model:value="row.${javaField}" class="w-full">
  156 + <Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
  157 + {{ option.label }}
  158 + </Select.Option>
  159 + </Select>
  160 + </template>
  161 + #elseif($column.htmlType == "checkbox")## 多选框
  162 + <template #${javaField}="{ row, column }">
  163 + <CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
  164 + </template>
  165 + #elseif($column.htmlType == "radio")## 单选框
  166 + <template #${javaField}="{ row, column }">
  167 + <RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
  168 + </template>
  169 + #elseif($column.htmlType == "datetime")## 时间框
  170 + <template #${javaField}="{ row }">
  171 + <DatePicker
  172 + v-model:value="row.${javaField}"
  173 + :showTime="true"
  174 + format="YYYY-MM-DD HH:mm:ss"
  175 + valueFormat='x'
  176 + />
  177 + </template>
  178 + #elseif($column.htmlType == "textarea")## 文本框
  179 + <template #${javaField}="{ row }">
  180 + <Textarea v-model:value="row.${javaField}" />
  181 + </template>
  182 + #end
  183 + #end
  184 + #end
  185 + </${subSimpleClassName}Grid>
  186 + <div class="flex justify-center">
  187 + <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
  188 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  189 + </Button>
  190 + </div>
  191 + #else
  192 + <${subSimpleClassName}Form class="mx-4" />
  193 + #end
  194 +</template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_inner.vue.vm
1 1 ## 主表的 normal 和 inner 使用相同的 form 表单
2   -#parse("codegen/vue3/views/components/form_sub_normal.vue.vm")
3 2 \ No newline at end of file
  3 +#parse("codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm")
4 4 \ No newline at end of file
... ...
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 &quot;@vben/icons&quot;;
15 15 import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
16 16 import type { OnActionClickParams } from '#/adapter/vxe-table';
17 17 import { useVbenVxeGrid } from '#/adapter/vxe-table';
18   -import { use${subSimpleClassName}GridColumns } from '../data';
  18 +import { use${subSimpleClassName}GridEditColumns } from '../data';
19 19 import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
20 20 #else
21 21 import { useVbenForm } from '#/adapter/form';
... ... @@ -43,7 +43,7 @@ function onActionClick({
43 43  
44 44 const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
45 45 gridOptions: {
46   - columns: use${subSimpleClassName}GridColumns(onActionClick),
  46 + columns: use${subSimpleClassName}GridEditColumns(onActionClick),
47 47 border: true,
48 48 showOverflow: true,
49 49 autoResize: true,
... ... @@ -73,13 +73,21 @@ const handleAdd = async () =&gt; {
73 73 /** 提供获取表格数据的方法供父组件调用 */
74 74 defineExpose({
75 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   - ];
  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];
83 91 },
84 92 });
85 93  
... ... @@ -94,6 +102,7 @@ watch(
94 102 await nextTick();
95 103 await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
96 104 },
  105 + { immediate: true },
97 106 );
98 107 #else
99 108 const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
... ... @@ -122,6 +131,7 @@ watch(
122 131 await nextTick();
123 132 await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
124 133 },
  134 + { immediate: true },
125 135 );
126 136 #end
127 137 </script>
... ...
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 @@
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 7 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
7   -<template>
8   - <!-- 列表 -->
9   - <ContentWrap>
10   -#if ($table.templateType == 11)
11   - <el-button
12   - type="primary"
13   - plain
14   - @click="openForm('create')"
15   - v-hasPermi="['${permissionPrefix}:create']"
16   - >
17   - <Icon icon="ep:plus" class="mr-5px" /> 新增
18   - </el-button>
19   -#end
20   - <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
21   - #foreach($column in $subColumns)
22   - #if ($column.listOperationResult)
23   - #set ($dictType=$column.dictType)
24   - #set ($javaField = $column.javaField)
25   - #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
26   - #set ($comment=$column.columnComment)
27   - #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
28   - #elseif ($column.javaType == "LocalDateTime")## 时间类型
29   - <el-table-column
30   - label="${comment}"
31   - align="center"
32   - prop="${javaField}"
33   - :formatter="dateFormatter"
34   - width="180px"
35   - />
36   - #elseif($column.dictType && "" != $column.dictType)## 数据字典
37   - <el-table-column label="${comment}" align="center" prop="${javaField}">
38   - <template #default="scope">
39   - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
40   - </template>
41   - </el-table-column>
42   - #else
43   - <el-table-column label="${comment}" align="center" prop="${javaField}" />
44   - #end
45   - #end
46   - #end
47   - #if ($table.templateType == 11)
48   - <el-table-column label="操作" align="center">
49   - <template #default="scope">
50   - <el-button
51   - link
52   - type="primary"
53   - @click="openForm('update', scope.row.id)"
54   - v-hasPermi="['${permissionPrefix}:update']"
55   - >
56   - 编辑
57   - </el-button>
58   - <el-button
59   - link
60   - type="danger"
61   - @click="handleDelete(scope.row.id)"
62   - v-hasPermi="['${permissionPrefix}:delete']"
63   - >
64   - 删除
65   - </el-button>
66   - </template>
67   - </el-table-column>
68   - #end
69   - </el-table>
70   - #if ($table.templateType == 11)
71   - <!-- 分页 -->
72   - <Pagination
73   - :total="total"
74   - v-model:page="queryParams.pageNo"
75   - v-model:limit="queryParams.pageSize"
76   - @pagination="getList"
77   - />
78   - #end
79   - </ContentWrap>
80   -#if ($table.templateType == 11)
81   - <!-- 表单弹窗:添加/修改 -->
82   - <${subSimpleClassName}Form ref="formRef" @success="getList" />
  8 +<script lang="ts" setup>
  9 + import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
  10 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  11 +
  12 + import { useVbenModal } from '@vben/common-ui';
  13 + import { Button, message } from 'ant-design-vue';
  14 + import { Plus } from '@vben/icons';
  15 + import { ref, h, nextTick,watch } from 'vue';
  16 + import { $t } from '#/locales';
  17 + import { useVbenVxeGrid } from '#/adapter/vxe-table';
  18 +
  19 +
  20 +#if ($table.templateType == 11) ## erp
  21 + import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
83 22 #end
84   -</template>
85   -<script setup lang="ts">
86   -import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
87   -import { dateFormatter } from '@/utils/formatTime'
88   -import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
89   -#if ($table.templateType == 11)
90   -import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
  23 + 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}';
91 28 #end
92 29  
93   -const { t } = useI18n() // 国际化
94   -const message = useMessage() // 消息弹窗
95   -
96 30 const props = defineProps<{
97   - ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
  31 + ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
98 32 }>()
99   -const loading = ref(false) // 列表的加载中
100   -const list = ref([]) // 列表的数据
101   -#if ($table.templateType == 11)
102   -const total = ref(0) // 列表的总页数
103   -const queryParams = reactive({
104   - pageNo: 1,
105   - pageSize: 10,
106   - ${subJoinColumn.javaField}: undefined as unknown
107   -})
108 33  
109   -/** 监听主表的关联字段的变化,加载对应的子表数据 */
110   -watch(
111   - () => props.${subJoinColumn.javaField},
112   - (val: number) => {
113   - if (!val) {
114   - return
115   - }
116   - queryParams.${subJoinColumn.javaField} = val
117   - handleQuery()
118   - },
119   - { immediate: true, deep: true }
120   -)
121   -#end
  34 +#if ($table.templateType == 11) ## erp
  35 + const [FormModal, formModalApi] = useVbenModal({
  36 + connectedComponent: ${subSimpleClassName}Form,
  37 + destroyOnClose: true,
  38 + });
  39 +
  40 +/** 创建${subTable.classComment} */
  41 +function onCreate() {
  42 + formModalApi.setData({}).open();
  43 +}
122 44  
123   -/** 查询列表 */
124   -const getList = async () => {
125   - loading.value = true
  45 +/** 编辑${subTable.classComment} */
  46 +function onEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
  47 + formModalApi.setData(row).open();
  48 +}
  49 +/** 删除${subTable.classComment} */
  50 +async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
  51 + const hideLoading = message.loading({
  52 + content: $t('ui.actionMessage.deleting', [row.id]),
  53 + duration: 0,
  54 + key: 'action_process_msg',
  55 + });
126 56 try {
127   -#if ($table.templateType == 11)
128   - const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
129   - list.value = data.list
130   - total.value = data.total
131   -#else
132   - #if ( $subTable.subJoinMany )
133   - list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
134   - #else
135   - const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
136   - if (!data) {
137   - return
138   - }
139   - list.value.push(data)
140   - #end
141   -#end
142   - } finally {
143   - loading.value = false
  57 + await delete${subSimpleClassName}(row.id as number);
  58 + message.success({
  59 + content: $t('ui.actionMessage.deleteSuccess', [row.id]),
  60 + key: 'action_process_msg',
  61 + });
  62 + onRefresh();
  63 + } catch {
  64 + hideLoading();
144 65 }
145 66 }
146 67  
147   -/** 搜索按钮操作 */
148   -const handleQuery = () => {
149   - queryParams.pageNo = 1
150   - getList()
  68 +/** 表格操作按钮的回调函数 */
  69 +function onActionClick({
  70 + code,
  71 + row,
  72 +}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
  73 + switch (code) {
  74 + case 'delete': {
  75 + onDelete(row);
  76 + break;
  77 + }
  78 + case 'edit': {
  79 + onEdit(row);
  80 + break;
  81 + }
  82 + }
151 83 }
  84 +#end
  85 + const [Grid, gridApi] = useVbenVxeGrid({
  86 + gridOptions: {
152 87 #if ($table.templateType == 11)
  88 + columns: use${subSimpleClassName}GridColumns(onActionClick),
  89 +#else
  90 + columns: use${subSimpleClassName}GridColumns(),
  91 +#end
  92 + height: 'auto',
  93 + rowConfig: {
  94 + keyField: 'id',
  95 + isHover: true,
  96 + },
  97 + pagerConfig: {
  98 + enabled: false,
  99 + },
  100 + toolbarConfig: {
  101 + enabled: false,
  102 + },
  103 + } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
  104 + });
153 105  
154   -/** 添加/修改操作 */
155   -const formRef = ref()
156   -const openForm = (type: string, id?: number) => {
157   - if (!props.${subJoinColumn.javaField}) {
158   - message.error('请选择一个${table.classComment}')
159   - return
160   - }
161   - formRef.value.open(type, id, props.${subJoinColumn.javaField})
  106 +/** 刷新表格 */
  107 +const onRefresh = async ()=> {
  108 + #if ($subTable.subJoinMany) ## 一对多
  109 + await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  110 + #else
  111 + await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
  112 + #end
162 113 }
163 114  
164   -/** 删除按钮操作 */
165   -const handleDelete = async (id: number) => {
166   - try {
167   - // 删除的二次确认
168   - await message.delConfirm()
169   - // 发起删除
170   - await ${simpleClassName}Api.delete${subSimpleClassName}(id)
171   - message.success(t('common.delSuccess'))
172   - // 刷新列表
173   - await getList()
174   - } catch {}
175   -}
176   -#end
177   -#if ($table.templateType != 11)
  115 + /** 监听主表的关联字段的变化,加载对应的子表数据 */
  116 + watch(
  117 + () => props.${subJoinColumn.javaField},
  118 + async (val) => {
  119 + if (!val) {
  120 + return;
  121 + }
178 122  
179   -/** 初始化 **/
180   -onMounted(() => {
181   - getList()
182   -})
183   -#end
184   -</script>
185 123 \ No newline at end of file
  124 + await nextTick();
  125 + await onRefresh()
  126 + },
  127 + { immediate: true },
  128 + );
  129 +</script>
  130 +
  131 +<template>
  132 + <div class="mx-4">
  133 + #if ($table.templateType == 11) ## erp
  134 + <FormModal @success="onRefresh" />
  135 + <Grid table-title="${subTable.classComment}列表">
  136 + <template #toolbar-tools>
  137 + <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${subTable.moduleName}:${subSimpleClassName_strikeCase}:create']">
  138 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  139 + </Button>
  140 + </template>
  141 + </Grid>
  142 + #else
  143 + <Grid table-title="${subTable.classComment}列表" />
  144 + #end
  145 + </div>
  146 +</template>
186 147 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_inner.vue.vm
1 1 ## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
2 2 ## 1)inner 使用 list 不分页,erp 使用 page 分页
3 3 ## 2)erp 支持单个子表的新增、修改、删除,inner 不支持
4   -#parse("codegen/vue3/views/components/list_sub_erp.vue.vm")
5 4 \ No newline at end of file
  5 +#parse("codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm")
6 6 \ No newline at end of file
... ...