Commit 01bdb33696344439a349750f83db48d31b6e26fc

Authored by zhijiantianya@gmail.com
1 parent 90842542

代码生成器:进一步完善 erp 生成模版

yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
... ... @@ -337,7 +337,7 @@ public class CodegenEngine {
337 337 String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName()));
338 338 subSimpleClassNames.add(subSimpleClassName);
339 339 subClassNameVars.add(lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType,用于变量
340   - subSimpleClassNameStrikeCases.add(toSymbolCase(simpleClassName, '-')); // 将 DictType 转换成 dict-type
  340 + subSimpleClassNameStrikeCases.add(toSymbolCase(subSimpleClassName, '-')); // 将 DictType 转换成 dict-type
341 341 }
342 342 bindingMap.put("subPrimaryColumns", subPrimaryColumns);
343 343 bindingMap.put("subJoinColumns", subJoinColumns);
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm
... ... @@ -15,6 +15,7 @@ import javax.servlet.http.*;
15 15 import java.util.*;
16 16 import java.io.IOException;
17 17  
  18 +import ${PageParamClassName};
18 19 import ${PageResultClassName};
19 20 import ${CommonResultClassName};
20 21 import static ${CommonResultClassName}.success;
... ... @@ -175,7 +176,7 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
175 176 #if ($sceneEnum.scene == 1)
176 177 @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
177 178 #end
178   - public CommonResult<Booealn> update${subSimpleClassName}(@Valid @RequestBody ${subTable.className}DO ${subClassNameVar}) {
  179 + public CommonResult<Boolean> update${subSimpleClassName}(@Valid @RequestBody ${subTable.className}DO ${subClassNameVar}) {
179 180 ${classNameVar}Service.update${subSimpleClassName}(${subClassNameVar});
180 181 return success(true);
181 182 }
... ... @@ -186,8 +187,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
186 187 #if ($sceneEnum.scene == 1)
187 188 @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
188 189 #end
189   - public CommonResult<Booealn> delete${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) {
190   - ${classNameVar}Service.delete${subSimpleClassName}(${subClassNameVar});
  190 + public CommonResult<Boolean> delete${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) {
  191 + ${classNameVar}Service.delete${subSimpleClassName}(id);
191 192 return success(true);
192 193 }
193 194  
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm
... ... @@ -42,7 +42,9 @@ public class ${sceneEnum.prefixClass}${table.className}BaseVO {
42 42  
43 43 #end
44 44 #end
45   -## 特殊:主子表专属逻辑
  45 +## 特殊:主子表专属逻辑(非 ERP 模式)
  46 +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
  47 +
46 48 #foreach ($subTable in $subTables)
47 49 #set ($index = $foreach.count - 1)
48 50 #if ( $subTable.subJoinMany)
... ... @@ -53,4 +55,5 @@ public class ${sceneEnum.prefixClass}${table.className}BaseVO {
53 55  
54 56 #end
55 57 #end
  58 +#end
56 59 }
57 60 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm
... ... @@ -9,6 +9,7 @@ import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.business
9 9 import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
10 10 #end
11 11 import ${PageResultClassName};
  12 +import ${PageParamClassName};
12 13  
13 14 /**
14 15 * ${table.classComment} Service 接口
... ... @@ -83,7 +84,7 @@ public interface ${table.className}Service {
83 84 * @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment}
84 85 * @return ${subTable.classComment}分页
85 86 */
86   - PageResult<${subTable.className}DO> get${subSimpleClassName}Page(PageParam pageReqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField})
  87 + PageResult<${subTable.className}DO> get${subSimpleClassName}Page(PageParam pageReqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField});
87 88  
88 89 ## 情况二:非 MASTER_ERP 时,需要列表查询子表
89 90 #else
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm
... ... @@ -13,6 +13,7 @@ import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.business
13 13 import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
14 14 #end
15 15 import ${PageResultClassName};
  16 +import ${PageParamClassName};
16 17  
17 18 import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert;
18 19 import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
... ... @@ -44,16 +45,16 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
44 45 #end
45 46  
46 47 @Override
47   -## 特殊:主子表专属逻辑
48   -#if ( $subTables && $subTables.size() > 0 )
  48 +## 特殊:主子表专属逻辑(非 ERP 模式)
  49 +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
49 50 @Transactional(rollbackFor = Exception.class)
50 51 #end
51 52 public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) {
52 53 // 插入
53 54 ${table.className}DO ${classNameVar} = ${table.className}Convert.INSTANCE.convert(createReqVO);
54 55 ${classNameVar}Mapper.insert(${classNameVar});
55   -## 特殊:主子表专属逻辑
56   -#if ( $subTables && $subTables.size() > 0)
  56 +## 特殊:主子表专属逻辑(非 ERP 模式)
  57 +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
57 58  
58 59 // 插入子表
59 60 #foreach ($subTable in $subTables)
... ... @@ -73,8 +74,8 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
73 74 }
74 75  
75 76 @Override
76   -## 特殊:主子表专属逻辑
77   -#if ( $subTables && $subTables.size() > 0)
  77 +## 特殊:主子表专属逻辑(非 ERP 模式)
  78 +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
78 79 @Transactional(rollbackFor = Exception.class)
79 80 #end
80 81 public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) {
... ... @@ -83,8 +84,8 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
83 84 // 更新
84 85 ${table.className}DO updateObj = ${table.className}Convert.INSTANCE.convert(updateReqVO);
85 86 ${classNameVar}Mapper.updateById(updateObj);
86   -## 特殊:主子表专属逻辑
87   -#if ( $subTables && $subTables.size() > 0)
  87 +## 特殊:主子表专属逻辑(非 ERP 模式)
  88 +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11)
88 89  
89 90 // 更新子表
90 91 #foreach ($subTable in $subTables)
... ... @@ -182,13 +183,13 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
182 183 ## 情况一:MASTER_ERP 时,支持单个的新增、修改、删除操作
183 184 #if ( $table.templateType == 11 )
184 185 @Override
185   - public ${subPrimaryColumn.javaType} create${subSimpleClassName}(@Valid ${subTable.className}DO ${subClassNameVar}) {
  186 + public ${subPrimaryColumn.javaType} create${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) {
186 187 ${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar});
187 188 return ${subClassNameVar}.getId();
188 189 }
189 190  
190 191 @Override
191   - public void update${subSimpleClassName}(@Valid ${subTable.className}DO ${subClassNameVar}) {
  192 + public void update${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) {
192 193 ${subClassNameVars.get($index)}Mapper.updateById(${subClassNameVar});
193 194 }
194 195  
... ... @@ -230,10 +231,10 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
230 231 }
231 232  
232 233 #end
  234 +#end
233 235 private void delete${subSimpleClassName}By${SubJoinColumnName}(${primaryColumn.javaType} ${subJoinColumn.javaField}) {
234 236 ${subClassNameVars.get($index)}Mapper.deleteBy${SubJoinColumnName}(${subJoinColumn.javaField});
235 237 }
236 238  
237 239 #end
238   -#end
239 240 }
240 241 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/_column.vm deleted
1   -## 提供给 baseVO、createVO、updateVO 生成字段
2   - @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
3   -#if (!${column.nullable})## 判断 @NotEmpty 和 @NotNull 注解
4   -#if (${column.javaType} == 'String')
5   - @NotEmpty(message = "${column.columnComment}不能为空")
6   -#else
7   - @NotNull(message = "${column.columnComment}不能为空")
8   -#end
9   -#end
10   -#if (${column.javaType} == "LocalDateTime")## 时间类型
11   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
12   -#end
13   - private ${column.javaType} ${column.javaField};
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm
  1 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  2 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  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.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 TODO 芋艿:这里要忽略下 join 字段;
  29 + <el-form-item label="${comment}" prop="${javaField}">
  30 + <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
  31 + </el-form-item>
  32 + #elseif($column.htmlType == "imageUpload")## 图片上传
  33 + <el-form-item label="${comment}">
  34 + <UploadImg v-model="formData.${javaField}" />
  35 + </el-form-item>
  36 + #elseif($column.htmlType == "fileUpload")## 文件上传
  37 + <el-form-item label="${comment}" prop="${javaField}">
  38 + <UploadFile v-model="formData.${javaField}" />
  39 + </el-form-item>
  40 + #elseif($column.htmlType == "editor")## 文本编辑器
  41 + <el-form-item label="${comment}" prop="${javaField}">
  42 + <Editor v-model="formData.${javaField}" height="150px" />
  43 + </el-form-item>
  44 + #elseif($column.htmlType == "select")## 下拉框
  45 + <el-form-item label="${comment}" prop="${javaField}">
  46 + <el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
  47 + #if ("" != $dictType)## 有数据字典
  48 + <el-option
  49 + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
  50 + :key="dict.value"
  51 + :label="dict.label"
  52 + :value="dict.value"
  53 + />
  54 + #else##没数据字典
  55 + <el-option label="请选择字典生成" value="" />
  56 + #end
  57 + </el-select>
  58 + </el-form-item>
  59 + #elseif($column.htmlType == "checkbox")## 多选框
  60 + <el-form-item label="${comment}" prop="${javaField}">
  61 + <el-checkbox-group v-model="formData.${javaField}">
  62 + #if ("" != $dictType)## 有数据字典
  63 + <el-checkbox
  64 + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
  65 + :key="dict.value"
  66 + :label="dict.value"
  67 + >
  68 + {{ dict.label }}
  69 + </el-checkbox>
  70 + #else##没数据字典
  71 + <el-checkbox>请选择字典生成</el-checkbox>
  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 label="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 * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
  117 +
  118 +const { t } = useI18n() // 国际化
  119 +const message = useMessage() // 消息弹窗
  120 +
  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
  134 +#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 +
  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.${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 + }
  161 + }
  162 +}
  163 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  164 +
  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 + }
  187 +}
  188 +
  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()
  203 +}
  204 +</script>
0 205 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_inner.vue.vm
1 1 ## 主表的 normal 和 inner 使用相同的 form 表单
2   -#parse("codegen/vue3/views/components/form_sub_inner.vue.vm")
3 2 \ No newline at end of file
  3 +#parse("codegen/vue3/views/components/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/views/components/list_sub_erp.vue.vm
... ... @@ -7,6 +7,14 @@
7 7 <template>
8 8 <!-- 列表 -->
9 9 <ContentWrap>
  10 + <el-button
  11 + type="primary"
  12 + plain
  13 + @click="openForm('create')"
  14 + v-hasPermi="['${permissionPrefix}:create']"
  15 + >
  16 + <Icon icon="ep:plus" class="mr-5px" /> 新增
  17 + </el-button>
10 18 <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
11 19 #foreach($column in $subColumns)
12 20 #if ($column.listOperationResult)
... ... @@ -66,27 +74,56 @@
66 74 />
67 75 #end
68 76 </ContentWrap>
  77 +
  78 + <!-- 表单弹窗:添加/修改 -->
  79 + <${subSimpleClassName}Form ref="formRef" @success="getList" />
69 80 </template>
70 81  
71 82 <script setup lang="ts">
72 83 import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
73 84 import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
  85 +import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
  86 +
  87 +const { t } = useI18n() // 国际化
  88 +const message = useMessage() // 消息弹窗
  89 +
74 90 const props = defineProps<{
75 91 ${subJoinColumn.javaField}: undefined // ${subJoinColumn.columnComment}(主表的关联字段)
76 92 }>()
77   -const loading = ref(true) // 列表的加载中
  93 +const loading = ref(false) // 列表的加载中
78 94 const list = ref([]) // 列表的数据
  95 +#if ($table.templateType == 11)
  96 +const total = ref(0) // 列表的总页数
  97 +const queryParams = reactive({
  98 + pageNo: 1,
  99 + pageSize: 10,
  100 + ${subJoinColumn.javaField}: undefined
  101 +})
  102 +
  103 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  104 +watch(
  105 + () => props.${subJoinColumn.javaField},
  106 + (val) => {
  107 + queryParams.${subJoinColumn.javaField} = val
  108 + handleQuery()
  109 + },
  110 + { immediate: false }
  111 +)
  112 +#end
79 113  
80 114 /** 查询列表 */
81 115 const getList = async () => {
82 116 loading.value = true
83 117 try {
84 118 #if ($table.templateType == 11)
  119 + const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
  120 + list.value = data.list
  121 + total.value = data.total
85 122 #else
86 123 #if ( $subTable.subJoinMany )
87   - list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}.props)
  124 + list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
88 125 #else
89   - const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}.props)
  126 + const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
90 127 if (!data) {
91 128 return
92 129 }
... ... @@ -98,8 +135,41 @@ const getList = async () =&gt; {
98 135 }
99 136 }
100 137  
  138 +/** 搜索按钮操作 */
  139 +const handleQuery = () => {
  140 + queryParams.pageNo = 1
  141 + getList()
  142 +}
  143 +#if ($table.templateType == 11)
  144 +
  145 +/** 添加/修改操作 */
  146 +const formRef = ref()
  147 +const openForm = (type: string, id?: number) => {
  148 + if (!props.${subJoinColumn.javaField}) {
  149 + message.error('请选择一个${table.classComment}')
  150 + return
  151 + }
  152 + formRef.value.open(type, id, props.${subJoinColumn.javaField})
  153 +}
  154 +
  155 +/** 删除按钮操作 */
  156 +const handleDelete = async (id: number) => {
  157 + try {
  158 + // 删除的二次确认
  159 + await message.delConfirm()
  160 + // 发起删除
  161 + await ${simpleClassName}Api.delete${subSimpleClassName}(id)
  162 + message.success(t('common.delSuccess'))
  163 + // 刷新列表
  164 + await getList()
  165 + } catch {}
  166 +}
  167 +#end
  168 +#if ($table.templateType != 11)
  169 +
101 170 /** 初始化 **/
102 171 onMounted(() => {
103 172 getList()
104 173 })
  174 +#end
105 175 </script>
106 176 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  6 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
1 7 <template>
2   - <ContentWrap>
3   - <!-- 搜索工作栏 -->
4   - <el-form
5   - class="-mb-15px"
6   - :model="queryParams"
7   - ref="queryFormRef"
8   - :inline="true"
9   - label-width="68px"
10   - >
11   - #foreach($column in $columns)
12   - #if ($column.listOperation)
13   - #set ($dictType = $column.dictType)
14   - #set ($javaField = $column.javaField)
15   - #set ($javaType = $column.javaType)
16   - #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
17   - #set ($comment = $column.columnComment)
18   - #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
19   - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
20   - #set ($dictMethod = "getIntDictOptions")
21   - #elseif ($javaType == "String")
22   - #set ($dictMethod = "getStrDictOptions")
23   - #elseif ($javaType == "Boolean")
24   - #set ($dictMethod = "getBoolDictOptions")
25   - #end
26   - #if ($column.htmlType == "input")
27   - <el-form-item label="${comment}" prop="${javaField}">
28   - <el-input
29   - v-model="queryParams.${javaField}"
30   - placeholder="请输入${comment}"
31   - clearable
32   - @keyup.enter="handleQuery"
33   - class="!w-240px"
34   - />
35   - </el-form-item>
36   - #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
37   - <el-form-item label="${comment}" prop="${javaField}">
38   - <el-select
39   - v-model="queryParams.${javaField}"
40   - placeholder="请选择${comment}"
41   - clearable
42   - class="!w-240px"
43   - >
44   - #if ("" != $dictType)## 设置了 dictType 数据字典的情况
45   - <el-option
46   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
47   - :key="dict.value"
48   - :label="dict.label"
49   - :value="dict.value"
50   - />
51   - #else## 未设置 dictType 数据字典的情况
52   - <el-option label="请选择字典生成" value="" />
53   - #end
54   - </el-select>
55   - </el-form-item>
56   - #elseif($column.htmlType == "datetime")
57   - #if ($column.listOperationCondition != "BETWEEN")## 非范围
58   - <el-form-item label="${comment}" prop="${javaField}">
59   - <el-date-picker
60   - v-model="queryParams.${javaField}"
61   - value-format="YYYY-MM-DD"
62   - type="date"
63   - placeholder="选择${comment}"
64   - clearable
65   - class="!w-240px"
66   - />
67   - </el-form-item>
68   - #else## 范围
69   - <el-form-item label="${comment}" prop="${javaField}">
70   - <el-date-picker
71   - v-model="queryParams.${javaField}"
72   - value-format="YYYY-MM-DD HH:mm:ss"
73   - type="daterange"
74   - start-placeholder="开始日期"
75   - end-placeholder="结束日期"
76   - :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
77   - class="!w-240px"
78   - />
79   - </el-form-item>
80   - #end
81   - #end
82   - #end
83   - #end
84   - <el-form-item>
85   - <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
86   - <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
87   - <el-button
88   - type="primary"
89   - plain
90   - @click="openForm('create')"
91   - v-hasPermi="['${permissionPrefix}:create']"
92   - >
93   - <Icon icon="ep:plus" class="mr-5px" /> 新增
94   - </el-button>
95   - <el-button
96   - type="success"
97   - plain
98   - @click="handleExport"
99   - :loading="exportLoading"
100   - v-hasPermi="['${permissionPrefix}:export']"
101   - >
102   - <Icon icon="ep:download" class="mr-5px" /> 导出
103   - </el-button>
104   - </el-form-item>
105   - </el-form>
106   - </ContentWrap>
107   -
108 8 <!-- 列表 -->
109 9 <ContentWrap>
  10 + <el-button
  11 + type="primary"
  12 + plain
  13 + @click="openForm('create')"
  14 + v-hasPermi="['${permissionPrefix}:create']"
  15 + >
  16 + <Icon icon="ep:plus" class="mr-5px" /> 新增
  17 + </el-button>
110 18 <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
111   - #foreach($column in $columns)
  19 + #foreach($column in $subColumns)
112 20 #if ($column.listOperationResult)
113 21 #set ($dictType=$column.dictType)
114 22 #set ($javaField = $column.javaField)
... ... @@ -133,6 +41,7 @@
133 41 #end
134 42 #end
135 43 #end
  44 + #if ($table.templateType == 11)
136 45 <el-table-column label="操作" align="center">
137 46 <template #default="scope">
138 47 <el-button
... ... @@ -153,7 +62,9 @@
153 62 </el-button>
154 63 </template>
155 64 </el-table-column>
  65 + #end
156 66 </el-table>
  67 + #if ($table.templateType == 11)
157 68 <!-- 分页 -->
158 69 <Pagination
159 70 :total="total"
... ... @@ -161,51 +72,64 @@
161 72 v-model:limit="queryParams.pageSize"
162 73 @pagination="getList"
163 74 />
  75 + #end
164 76 </ContentWrap>
165 77  
166   - <!-- 表单弹窗:添加/修改 -->
167   - <${simpleClassName}Form ref="formRef" @success="getList" />
  78 + <!-- 表单弹窗:添加/修改 -->
  79 + <${subSimpleClassName}Form ref="formRef" @success="getList" />
168 80 </template>
169 81  
170 82 <script setup lang="ts">
171 83 import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
172   -import { dateFormatter } from '@/utils/formatTime'
173   -import download from '@/utils/download'
174 84 import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
175   -import ${simpleClassName}Form from './${simpleClassName}Form.vue'
176   -
177   -defineOptions({ name: '${table.className}' })
  85 +import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
178 86  
179   -const message = useMessage() // 消息弹窗
180 87 const { t } = useI18n() // 国际化
  88 +const message = useMessage() // 消息弹窗
181 89  
182   -const loading = ref(true) // 列表的加载中
183   -const total = ref(0) // 列表的总页数
  90 +const props = defineProps<{
  91 + ${subJoinColumn.javaField}: undefined // ${subJoinColumn.columnComment}(主表的关联字段)
  92 +}>()
  93 +const loading = ref(false) // 列表的加载中
184 94 const list = ref([]) // 列表的数据
  95 +#if ($table.templateType == 11)
  96 +const total = ref(0) // 列表的总页数
185 97 const queryParams = reactive({
186 98 pageNo: 1,
187 99 pageSize: 10,
188   - #foreach ($column in $columns)
189   - #if ($column.listOperation)
190   - #if ($column.listOperationCondition != 'BETWEEN')
191   - $column.javaField: null,
192   - #end
193   - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
194   - $column.javaField: [],
195   - #end
196   - #end
197   - #end
  100 + ${subJoinColumn.javaField}: undefined
198 101 })
199   -const queryFormRef = ref() // 搜索的表单
200   -const exportLoading = ref(false) // 导出的加载中
  102 +
  103 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  104 +watch(
  105 + () => props.${subJoinColumn.javaField},
  106 + (val) => {
  107 + queryParams.${subJoinColumn.javaField} = val
  108 + handleQuery()
  109 + },
  110 + { immediate: false }
  111 +)
  112 +#end
201 113  
202 114 /** 查询列表 */
203 115 const getList = async () => {
204 116 loading.value = true
205 117 try {
206   - const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams)
  118 +#if ($table.templateType == 11)
  119 + const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
207 120 list.value = data.list
208 121 total.value = data.total
  122 +#else
  123 + #if ( $subTable.subJoinMany )
  124 + list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
  125 + #else
  126 + const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
  127 + if (!data) {
  128 + return
  129 + }
  130 + list.value.push(data)
  131 + #end
  132 +#end
209 133 } finally {
210 134 loading.value = false
211 135 }
... ... @@ -216,17 +140,16 @@ const handleQuery = () =&gt; {
216 140 queryParams.pageNo = 1
217 141 getList()
218 142 }
219   -
220   -/** 重置按钮操作 */
221   -const resetQuery = () => {
222   - queryFormRef.value.resetFields()
223   - handleQuery()
224   -}
  143 +#if ($table.templateType == 11)
225 144  
226 145 /** 添加/修改操作 */
227 146 const formRef = ref()
228 147 const openForm = (type: string, id?: number) => {
229   - formRef.value.open(type, id)
  148 + if (!props.${subJoinColumn.javaField}) {
  149 + message.error('请选择一个${table.classComment}')
  150 + return
  151 + }
  152 + formRef.value.open(type, id, props.${subJoinColumn.javaField})
230 153 }
231 154  
232 155 /** 删除按钮操作 */
... ... @@ -235,30 +158,18 @@ const handleDelete = async (id: number) =&gt; {
235 158 // 删除的二次确认
236 159 await message.delConfirm()
237 160 // 发起删除
238   - await ${simpleClassName}Api.delete${simpleClassName}(id)
  161 + await ${simpleClassName}Api.delete${subSimpleClassName}(id)
239 162 message.success(t('common.delSuccess'))
240 163 // 刷新列表
241 164 await getList()
242 165 } catch {}
243 166 }
244   -
245   -/** 导出按钮操作 */
246   -const handleExport = async () => {
247   - try {
248   - // 导出的二次确认
249   - await message.exportConfirm()
250   - // 发起导出
251   - exportLoading.value = true
252   - const data = await ${simpleClassName}Api.export${simpleClassName}(queryParams)
253   - download.excel(data, '${table.classComment}.xls')
254   - } catch {
255   - } finally {
256   - exportLoading.value = false
257   - }
258   -}
  167 +#end
  168 +#if ($table.templateType != 11)
259 169  
260 170 /** 初始化 **/
261 171 onMounted(() => {
262 172 getList()
263 173 })
  174 +#end
264 175 </script>
265 176 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineTest.java
... ... @@ -469,7 +469,8 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
469 469 .setTableName("infra_demo12_student").setTableComment("学生表")
470 470 .setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12Student")
471 471 .setClassComment("学生").setAuthor("芋道源码")
472   - .setTemplateType(CodegenTemplateTypeEnum.MASTER_INNER.getType())
  472 +// .setTemplateType(CodegenTemplateTypeEnum.MASTER_INNER.getType())
  473 + .setTemplateType(CodegenTemplateTypeEnum.MASTER_ERP.getType())
473 474 .setFrontType(CodegenFrontTypeEnum.VUE3.getType());
474 475 CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
475 476 .setId(100L)
... ...