Commit 0a8257a565bb17ad53c32bddb3aca3740fdebddc
1 parent
055eb350
代码生成:主子表 normal 模式,1 对多的 form 生成
Showing
9 changed files
with
391 additions
and
25 deletions
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | +import cn.hutool.core.util.ObjectUtil; | |
| 5 | 6 | import cn.hutool.core.util.StrUtil; |
| 6 | 7 | import cn.hutool.extra.template.TemplateConfig; |
| 7 | 8 | import cn.hutool.extra.template.TemplateEngine; |
| ... | ... | @@ -27,6 +28,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 27 | 28 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; |
| 28 | 29 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; |
| 29 | 30 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; |
| 31 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; | |
| 30 | 32 | import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; |
| 31 | 33 | import com.google.common.annotations.VisibleForTesting; |
| 32 | 34 | import com.google.common.collect.ImmutableTable; |
| ... | ... | @@ -111,6 +113,16 @@ public class CodegenEngine { |
| 111 | 113 | vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) |
| 112 | 114 | .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/form.vue"), |
| 113 | 115 | vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue")) |
| 116 | + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑 | |
| 117 | + vue3FilePath("views/${table.moduleName}/${classNameVar}/components/${subSimpleClassName}Form.vue")) | |
| 118 | + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑 | |
| 119 | + vue3FilePath("views/${table.moduleName}/${classNameVar}/components/${subSimpleClassName}Form.vue")) | |
| 120 | + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_erp.vue"), // 特殊:主子表专属逻辑 | |
| 121 | + vue3FilePath("views/${table.moduleName}/${classNameVar}/components/${subSimpleClassName}Form.vue")) | |
| 122 | + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_inner.vue"), // 特殊:主子表专属逻辑 | |
| 123 | + vue3FilePath("views/${table.moduleName}/${classNameVar}/components/${subSimpleClassName}List.vue")) | |
| 124 | + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_erp.vue"), // 特殊:主子表专属逻辑 | |
| 125 | + vue3FilePath("views/${table.moduleName}/${classNameVar}/components/${subSimpleClassName}List.vue")) | |
| 114 | 126 | .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"), |
| 115 | 127 | vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) |
| 116 | 128 | // Vue3 Schema 模版 |
| ... | ... | @@ -202,17 +214,9 @@ public class CodegenEngine { |
| 202 | 214 | templates.forEach((vmPath, filePath) -> { |
| 203 | 215 | // 2.1 特殊:主子表专属逻辑 |
| 204 | 216 | if (isSubTemplate(vmPath)) { |
| 205 | - if (CollUtil.isEmpty(subTables)) { | |
| 206 | - return; | |
| 207 | - } | |
| 208 | - for (int i = 0; i < subTables.size(); i++) { | |
| 209 | - bindingMap.put("subIndex", i); | |
| 210 | - generateCode(result, vmPath, filePath, bindingMap); | |
| 211 | - } | |
| 212 | - bindingMap.remove("subIndex"); | |
| 217 | + generateSubCode(table, subTables, result, vmPath, filePath, bindingMap); | |
| 213 | 218 | return; |
| 214 | 219 | } |
| 215 | - | |
| 216 | 220 | // 2.2 默认生成 |
| 217 | 221 | generateCode(result, vmPath, filePath, bindingMap); |
| 218 | 222 | }); |
| ... | ... | @@ -228,6 +232,35 @@ public class CodegenEngine { |
| 228 | 232 | result.put(filePath, content); |
| 229 | 233 | } |
| 230 | 234 | |
| 235 | + private void generateSubCode(CodegenTableDO table, List<CodegenTableDO> subTables, | |
| 236 | + Map<String, String> result, String vmPath, | |
| 237 | + String filePath, Map<String, Object> bindingMap) { | |
| 238 | + // 没有子表,所以不生成 | |
| 239 | + if (CollUtil.isEmpty(subTables)) { | |
| 240 | + return; | |
| 241 | + } | |
| 242 | + // 主子表的模式匹配。目的:过滤掉个性化的模版 | |
| 243 | + if (vmPath.contains("_normal") | |
| 244 | + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_NORMAL.getType())) { | |
| 245 | + return; | |
| 246 | + } | |
| 247 | + if (vmPath.contains("_erp") | |
| 248 | + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_ERP.getType())) { | |
| 249 | + return; | |
| 250 | + } | |
| 251 | + if (vmPath.contains("_inner") | |
| 252 | + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_INNER.getType())) { | |
| 253 | + return; | |
| 254 | + } | |
| 255 | + | |
| 256 | + // 逐个生成 | |
| 257 | + for (int i = 0; i < subTables.size(); i++) { | |
| 258 | + bindingMap.put("subIndex", i); | |
| 259 | + generateCode(result, vmPath, filePath, bindingMap); | |
| 260 | + } | |
| 261 | + bindingMap.remove("subIndex"); | |
| 262 | + } | |
| 263 | + | |
| 231 | 264 | /** |
| 232 | 265 | * 格式化生成后的代码 |
| 233 | 266 | * |
| ... | ... | @@ -323,6 +356,7 @@ public class CodegenEngine { |
| 323 | 356 | return templates; |
| 324 | 357 | } |
| 325 | 358 | |
| 359 | + @SuppressWarnings("unchecked") | |
| 326 | 360 | private String formatFilePath(String filePath, Map<String, Object> bindingMap) { |
| 327 | 361 | filePath = StrUtil.replace(filePath, "${basePackage}", |
| 328 | 362 | getStr(bindingMap, "basePackage").replaceAll("\\.", "/")); |
| ... | ... | @@ -346,6 +380,8 @@ public class CodegenEngine { |
| 346 | 380 | filePath = StrUtil.replace(filePath, "${subTable.moduleName}", subTable.getModuleName()); |
| 347 | 381 | filePath = StrUtil.replace(filePath, "${subTable.businessName}", subTable.getBusinessName()); |
| 348 | 382 | filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName()); |
| 383 | + filePath = StrUtil.replace(filePath, "${subSimpleClassName}", | |
| 384 | + ((List<String>) bindingMap.get("subSimpleClassNames")).get(subIndex)); | |
| 349 | 385 | } |
| 350 | 386 | return filePath; |
| 351 | 387 | } |
| ... | ... | @@ -417,4 +453,5 @@ public class CodegenEngine { |
| 417 | 453 | private static boolean isSubTemplate(String path) { |
| 418 | 454 | return path.contains("_sub"); |
| 419 | 455 | } |
| 456 | + | |
| 420 | 457 | } | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm
| ... | ... | @@ -43,4 +43,57 @@ export const delete${simpleClassName} = async (id: number) => { |
| 43 | 43 | // 导出${table.classComment} Excel |
| 44 | 44 | export const export${simpleClassName} = async (params) => { |
| 45 | 45 | return await request.download({ url: `${baseURL}/export-excel`, params }) |
| 46 | -} | |
| 47 | 46 | \ No newline at end of file |
| 47 | +} | |
| 48 | +## 特殊:主子表专属逻辑 | |
| 49 | +#foreach ($subTable in $subTables) | |
| 50 | +#set ($index = $foreach.count - 1) | |
| 51 | +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) | |
| 52 | +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 | |
| 53 | +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 | |
| 54 | +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 | |
| 55 | +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index)) | |
| 56 | +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) | |
| 57 | +#set ($subClassNameVar = $subClassNameVars.get($index)) | |
| 58 | + | |
| 59 | +// ==================== 子表($subTable.classComment) ==================== | |
| 60 | +## 情况一:MASTER_ERP 时,需要分查询页子表 | |
| 61 | +#if ( $table.templateType == 11 ) | |
| 62 | + | |
| 63 | +// 获得${subTable.classComment}分页 | |
| 64 | +export const get${subSimpleClassName}Page = async (params) => { | |
| 65 | + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/page`, params }) | |
| 66 | +} | |
| 67 | +## 情况二:非 MASTER_ERP 时,需要列表查询子表 | |
| 68 | +#else | |
| 69 | + #if ( $subTable.subJoinMany ) | |
| 70 | + | |
| 71 | +// 获得${subTable.classComment}列表 | |
| 72 | +export const get${subSimpleClassName}ListBy${SubJoinColumnName} = async (${subJoinColumn.javaField}) => { | |
| 73 | + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) | |
| 74 | +} | |
| 75 | + #else | |
| 76 | + | |
| 77 | +// 获得${subTable.classComment} | |
| 78 | +export const get${subSimpleClassName}By${SubJoinColumnName} = async (${subJoinColumn.javaField}) => { | |
| 79 | + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}`, ${subJoinColumn.javaField} }) | |
| 80 | +} | |
| 81 | + #end | |
| 82 | +#end | |
| 83 | +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 | |
| 84 | +#if ( $table.templateType == 11 ) | |
| 85 | +// 新增${subTable.classComment} | |
| 86 | +export const create${subSimpleClassName} = async (data) => { | |
| 87 | + return await request.post({ url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, data }) | |
| 88 | +} | |
| 89 | + | |
| 90 | +// 修改${subTable.classComment} | |
| 91 | +export const update${subSimpleClassName} = async (data) => { | |
| 92 | + return await request.put({ url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, data }) | |
| 93 | +} | |
| 94 | + | |
| 95 | +// 删除${subTable.classComment} | |
| 96 | +export const delete${subSimpleClassName} = async (id: number) => { | |
| 97 | + return await request.delete({ url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id }) | |
| 98 | +} | |
| 99 | +#end | |
| 100 | +#end | |
| 48 | 101 | \ No newline at end of file | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub.vue.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_inner.vue.vm
0 → 100644
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_normal.vue.vm
0 → 100644
| 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)})##首字母大写 | |
| 7 | +<template> | |
| 8 | + <el-form | |
| 9 | + ref="formRef" | |
| 10 | + :model="formData" | |
| 11 | + :rules="formRules" | |
| 12 | + v-loading="formLoading" | |
| 13 | + label-width="0px" | |
| 14 | + :inline-message="true" | |
| 15 | + > | |
| 16 | + <el-table :data="formData" class="-mt-10px"> | |
| 17 | + <el-table-column label="序号" type="index" width="100" /> | |
| 18 | +#foreach($column in $subColumns) | |
| 19 | + #if ($column.createOperation || $column.updateOperation) | |
| 20 | + #set ($dictType = $column.dictType) | |
| 21 | + #set ($javaField = $column.javaField) | |
| 22 | + #set ($javaType = $column.javaType) | |
| 23 | + #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) | |
| 24 | + #set ($comment = $column.columnComment) | |
| 25 | + #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法 | |
| 26 | + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | |
| 27 | + #set ($dictMethod = "getIntDictOptions") | |
| 28 | + #elseif ($javaType == "String") | |
| 29 | + #set ($dictMethod = "getStrDictOptions") | |
| 30 | + #elseif ($javaType == "Boolean") | |
| 31 | + #set ($dictMethod = "getBoolDictOptions") | |
| 32 | + #end | |
| 33 | + #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 TODO 芋艿:这里要忽略下 join 字段; | |
| 34 | + <el-table-column label="${comment}" width="150"> | |
| 35 | + <template #default="{ row, $index }"> | |
| 36 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 37 | + <el-input v-model="row.${javaField}" placeholder="请输入${comment}" /> | |
| 38 | + </el-form-item> | |
| 39 | + </template> | |
| 40 | + </el-table-column> | |
| 41 | + #elseif($column.htmlType == "imageUpload")## 图片上传 | |
| 42 | + <el-table-column label="${comment}" width="200"> | |
| 43 | + <template #default="{ row, $index }"> | |
| 44 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 45 | + <UploadImg v-model="row.${javaField}" /> | |
| 46 | + </el-form-item> | |
| 47 | + </template> | |
| 48 | + </el-table-column> | |
| 49 | + #elseif($column.htmlType == "fileUpload")## 文件上传 | |
| 50 | + <el-table-column label="${comment}" width="200"> | |
| 51 | + <template #default="{ row, $index }"> | |
| 52 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 53 | + <UploadFile v-model="row.${javaField}" /> | |
| 54 | + </el-form-item> | |
| 55 | + </template> | |
| 56 | + </el-table-column> | |
| 57 | + #elseif($column.htmlType == "editor")## 文本编辑器 | |
| 58 | + <el-table-column label="${comment}" width="400"> | |
| 59 | + <template #default="{ row, $index }"> | |
| 60 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 61 | + <Editor v-model="row.${javaField}" height="150px" /> | |
| 62 | + </el-form-item> | |
| 63 | + </template> | |
| 64 | + </el-table-column> | |
| 65 | + #elseif($column.htmlType == "select")## 下拉框 | |
| 66 | + <el-table-column label="${comment}" width="150"> | |
| 67 | + <template #default="{ row, $index }"> | |
| 68 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 69 | + <el-select v-model="row.${javaField}" placeholder="请选择${comment}"> | |
| 70 | + #if ("" != $dictType)## 有数据字典 | |
| 71 | + <el-option | |
| 72 | + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | |
| 73 | + :key="dict.value" | |
| 74 | + :label="dict.label" | |
| 75 | + :value="dict.value" | |
| 76 | + /> | |
| 77 | + #else##没数据字典 | |
| 78 | + <el-option label="请选择字典生成" value="" /> | |
| 79 | + #end | |
| 80 | + </el-select> | |
| 81 | + </el-form-item> | |
| 82 | + </template> | |
| 83 | + </el-table-column> | |
| 84 | + #elseif($column.htmlType == "checkbox")## 多选框 | |
| 85 | + <el-table-column label="${comment}" width="150"> | |
| 86 | + <template #default="{ row, $index }"> | |
| 87 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 88 | + <el-checkbox-group v-model="row.${javaField}"> | |
| 89 | + #if ("" != $dictType)## 有数据字典 | |
| 90 | + <el-checkbox | |
| 91 | + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | |
| 92 | + :key="dict.value" | |
| 93 | + :label="dict.value" | |
| 94 | + > | |
| 95 | + {{ dict.label }} | |
| 96 | + </el-checkbox> | |
| 97 | + #else##没数据字典 | |
| 98 | + <el-checkbox>请选择字典生成</el-checkbox> | |
| 99 | + #end | |
| 100 | + </el-checkbox-group> | |
| 101 | + </el-form-item> | |
| 102 | + </template> | |
| 103 | + </el-table-column> | |
| 104 | + #elseif($column.htmlType == "radio")## 单选框 | |
| 105 | + <el-table-column label="${comment}" width="150"> | |
| 106 | + <template #default="{ row, $index }"> | |
| 107 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 108 | + <el-radio-group v-model="row.${javaField}"> | |
| 109 | + #if ("" != $dictType)## 有数据字典 | |
| 110 | + <el-radio | |
| 111 | + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | |
| 112 | + :key="dict.value" | |
| 113 | + :label="dict.value" | |
| 114 | + > | |
| 115 | + {{ dict.label }} | |
| 116 | + </el-radio> | |
| 117 | + #else##没数据字典 | |
| 118 | + <el-radio label="1">请选择字典生成</el-radio> | |
| 119 | + #end | |
| 120 | + </el-radio-group> | |
| 121 | + </el-form-item> | |
| 122 | + </template> | |
| 123 | + </el-table-column> | |
| 124 | + #elseif($column.htmlType == "datetime")## 时间框 | |
| 125 | + <el-table-column label="${comment}" width="150"> | |
| 126 | + <template #default="{ row, $index }"> | |
| 127 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 128 | + <el-date-picker | |
| 129 | + v-model="row.${javaField}" | |
| 130 | + type="date" | |
| 131 | + value-format="x" | |
| 132 | + placeholder="选择${comment}" | |
| 133 | + /> | |
| 134 | + </el-form-item> | |
| 135 | + </template> | |
| 136 | + </el-table-column> | |
| 137 | + #elseif($column.htmlType == "textarea")## 文本框 | |
| 138 | + <el-table-column label="${comment}" width="200"> | |
| 139 | + <template #default="{ row, $index }"> | |
| 140 | + <el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!"> | |
| 141 | + <el-input v-model="row.${javaField}" type="textarea" placeholder="请输入${comment}" /> | |
| 142 | + </el-form-item> | |
| 143 | + </template> | |
| 144 | + </el-table-column> | |
| 145 | + #end | |
| 146 | + #end | |
| 147 | +#end | |
| 148 | + </el-table> | |
| 149 | + </el-form> | |
| 150 | + <el-row justify="center" class="mt-3"> | |
| 151 | + <el-button @click="handleAdd" round>+ 添加${subTable.classComment}</el-button> | |
| 152 | + </el-row> | |
| 153 | +</template> | |
| 154 | +<script setup lang="ts"> | |
| 155 | +import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' | |
| 156 | +import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}' | |
| 157 | + | |
| 158 | +const props = defineProps<{ | |
| 159 | + ${subJoinColumn.javaField}: undefined // ${subJoinColumn.columnComment}(主表的关联字段) | |
| 160 | +}>() | |
| 161 | +const formLoading = ref(false) // 表单的加载中 | |
| 162 | +const formData = ref([]) | |
| 163 | +const formRules = reactive({ | |
| 164 | +#foreach ($column in $subColumns) | |
| 165 | + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 | |
| 166 | + #set($comment=$column.columnComment) | |
| 167 | + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }], | |
| 168 | + #end | |
| 169 | +#end | |
| 170 | +}) | |
| 171 | +const formRef = ref() // 表单 Ref | |
| 172 | + | |
| 173 | +/** 监听主表的关联字段的变化,加载对应的子表数据 */ | |
| 174 | +watch( | |
| 175 | + () => props.${subJoinColumn.javaField}, | |
| 176 | + async (val) => { | |
| 177 | + // 情况一:val 为空,说明是新增,则置空 | |
| 178 | + if (!val) { | |
| 179 | + formData.value = [] | |
| 180 | + return; | |
| 181 | + } | |
| 182 | + // 情况二:val 非空,说明是修改,则加载数据 | |
| 183 | + try { | |
| 184 | + formLoading.value = true | |
| 185 | + formData.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(val) | |
| 186 | + } finally { | |
| 187 | + formLoading.value = false | |
| 188 | + } | |
| 189 | + }, | |
| 190 | + { immediate: true } | |
| 191 | +) | |
| 192 | + | |
| 193 | +/** 新增按钮操作 */ | |
| 194 | +const handleAdd = () => { | |
| 195 | + const row = { | |
| 196 | +#foreach ($column in $subColumns) | |
| 197 | + #if ($column.createOperation || $column.updateOperation) | |
| 198 | + #if ($column.htmlType == "checkbox") | |
| 199 | + $column.javaField: [], | |
| 200 | + #else | |
| 201 | + $column.javaField: undefined, | |
| 202 | + #end | |
| 203 | + #end | |
| 204 | +#end | |
| 205 | + } | |
| 206 | + row.${subJoinColumn.javaField} = props.${subJoinColumn.javaField} | |
| 207 | + formData.value.push(row) | |
| 208 | +} | |
| 209 | + | |
| 210 | +/** 删除按钮操作 */ | |
| 211 | +const handleDelete = (index) => { | |
| 212 | + formData.value.splice(index, 1) | |
| 213 | +} | |
| 214 | + | |
| 215 | +/** 表单校验 */ | |
| 216 | +const validate = () => { | |
| 217 | + return formRef.value.validate() | |
| 218 | +} | |
| 219 | + | |
| 220 | +/** 表单值 */ | |
| 221 | +const getData = () => { | |
| 222 | + return formData.value | |
| 223 | +} | |
| 224 | + | |
| 225 | +defineExpose({ validate, getData }) | |
| 226 | +</script> | |
| 0 | 227 | \ No newline at end of file | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub.vue.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_inner.vue.vm
0 → 100644
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm
| ... | ... | @@ -27,12 +27,10 @@ |
| 27 | 27 | <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" /> |
| 28 | 28 | </el-form-item> |
| 29 | 29 | #elseif($column.htmlType == "imageUpload")## 图片上传 |
| 30 | - #set ($hasImageUploadColumn = true) | |
| 31 | 30 | <el-form-item label="${comment}"> |
| 32 | 31 | <UploadImg v-model="formData.${javaField}" /> |
| 33 | 32 | </el-form-item> |
| 34 | 33 | #elseif($column.htmlType == "fileUpload")## 文件上传 |
| 35 | - #set ($hasFileUploadColumn = true) | |
| 36 | 34 | <el-form-item label="${comment}"> |
| 37 | 35 | <UploadFile v-model="formData.${javaField}" /> |
| 38 | 36 | </el-form-item> |
| ... | ... | @@ -124,11 +122,11 @@ const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| 124 | 122 | const formData = ref({ |
| 125 | 123 | #foreach ($column in $columns) |
| 126 | 124 | #if ($column.createOperation || $column.updateOperation) |
| 127 | - #if ($column.htmlType == "checkbox") | |
| 125 | + #if ($column.htmlType == "checkbox") | |
| 128 | 126 | $column.javaField: [], |
| 129 | - #else | |
| 127 | + #else | |
| 130 | 128 | $column.javaField: undefined, |
| 131 | - #end | |
| 129 | + #end | |
| 132 | 130 | #end |
| 133 | 131 | #end |
| 134 | 132 | }) | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineTest.java
| ... | ... | @@ -208,7 +208,63 @@ public class CodegenEngineTest extends BaseMockitoUnitTest { |
| 208 | 208 | .setCreateOperation(true).setUpdateOperation(true).setListOperation(true) |
| 209 | 209 | .setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition()).setListOperationResult(true) |
| 210 | 210 | .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType()); |
| 211 | - List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn, contactNameColumn); | |
| 211 | + CodegenColumnDO contactsAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name()) | |
| 212 | + .setColumnComment("头像").setNullable(false).setPrimaryKey(false) | |
| 213 | + .setOrdinalPosition(4).setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png") | |
| 214 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(false) | |
| 215 | + .setListOperationResult(true) | |
| 216 | + .setHtmlType(CodegenColumnHtmlTypeEnum.UPLOAD_IMAGE.getType()); | |
| 217 | + CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name()) | |
| 218 | + .setColumnComment("视频").setNullable(false).setPrimaryKey(false) | |
| 219 | + .setOrdinalPosition(5).setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4") | |
| 220 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(false) | |
| 221 | + .setListOperationResult(true) | |
| 222 | + .setHtmlType(CodegenColumnHtmlTypeEnum.UPLOAD_FILE.getType()); | |
| 223 | + CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name()) | |
| 224 | + .setColumnComment("个人简介").setNullable(false).setPrimaryKey(false) | |
| 225 | + .setOrdinalPosition(6).setJavaType("String").setJavaField("description").setExample("我是介绍") | |
| 226 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(false) | |
| 227 | + .setListOperationResult(true) | |
| 228 | + .setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType()); | |
| 229 | + CodegenColumnDO contactSex1Column = new CodegenColumnDO().setColumnName("sex1").setDataType(JdbcType.VARCHAR.name()) | |
| 230 | + .setColumnComment("性别 1").setNullable(false).setPrimaryKey(false) | |
| 231 | + .setOrdinalPosition(7).setJavaType("String").setJavaField("sex1").setExample("男") | |
| 232 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(true) | |
| 233 | + .setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition()).setListOperationResult(true) | |
| 234 | + .setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType()).setDictType("system_sex1"); | |
| 235 | + CodegenColumnDO contactSex2Column = new CodegenColumnDO().setColumnName("sex2").setDataType(JdbcType.INTEGER.name()) | |
| 236 | + .setColumnComment("性别 2").setNullable(false).setPrimaryKey(false) | |
| 237 | + .setOrdinalPosition(8).setJavaType("Integer").setJavaField("sex2").setExample("1") | |
| 238 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(true) | |
| 239 | + .setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition()).setListOperationResult(true) | |
| 240 | + .setHtmlType(CodegenColumnHtmlTypeEnum.CHECKBOX.getType()).setDictType("system_sex2"); | |
| 241 | + CodegenColumnDO contactSex3Column = new CodegenColumnDO().setColumnName("sex3").setDataType(JdbcType.BOOLEAN.name()) | |
| 242 | + .setColumnComment("性别 3").setNullable(false).setPrimaryKey(false) | |
| 243 | + .setOrdinalPosition(9).setJavaType("Boolean").setJavaField("sex3").setExample("true") | |
| 244 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(true) | |
| 245 | + .setListOperationResult(true) | |
| 246 | + .setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType()).setDictType("system_sex3"); | |
| 247 | + CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name()) | |
| 248 | + .setColumnComment("出生日期").setNullable(false).setPrimaryKey(false) | |
| 249 | + .setOrdinalPosition(10).setJavaType("LocalDateTime").setJavaField("birthday") | |
| 250 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(true) | |
| 251 | + .setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition()).setListOperationResult(true) | |
| 252 | + .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType()); | |
| 253 | + CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name()) | |
| 254 | + .setColumnComment("备注").setNullable(false).setPrimaryKey(false) | |
| 255 | + .setOrdinalPosition(11).setJavaType("String").setJavaField("memo").setExample("我是备注") | |
| 256 | + .setCreateOperation(true).setUpdateOperation(true).setListOperation(false) | |
| 257 | + .setListOperationResult(true) | |
| 258 | + .setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType()); | |
| 259 | + CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name()) | |
| 260 | + .setColumnComment("创建时间").setNullable(false).setPrimaryKey(false) | |
| 261 | + .setOrdinalPosition(12).setJavaType("LocalDateTime").setJavaField("createTime") | |
| 262 | + .setCreateOperation(false).setUpdateOperation(false).setListOperation(true) | |
| 263 | + .setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition()).setListOperationResult(true) | |
| 264 | + .setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType()); | |
| 265 | + List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn, | |
| 266 | + contactNameColumn, contactsAvatarColumn, contactVideoColumn, contactDescriptionColumn, | |
| 267 | + contactSex1Column, contactSex2Column, contactSex3Column, contactBirthdayColumn, contactMemoColumn, contactCreateTimeColumn); | |
| 212 | 268 | // 子表(地址) |
| 213 | 269 | CodegenTableDO addressTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()) |
| 214 | 270 | .setTableName("infra_demo_student_address").setTableComment("学生地址表") |
| ... | ... | @@ -222,26 +278,20 @@ public class CodegenEngineTest extends BaseMockitoUnitTest { |
| 222 | 278 | .setOrdinalPosition(1).setJavaType("Long").setJavaField("id").setExample("1024") |
| 223 | 279 | .setCreateOperation(false).setUpdateOperation(true).setListOperation(false) |
| 224 | 280 | .setListOperationResult(true); |
| 225 | - CodegenColumnDO addressStudentColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name()) | |
| 281 | + CodegenColumnDO addressStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name()) | |
| 226 | 282 | .setColumnComment("学生编号").setNullable(false).setPrimaryKey(false) |
| 227 | 283 | .setOrdinalPosition(2).setJavaType("Long").setJavaField("studentId").setExample("2048") |
| 228 | 284 | .setCreateOperation(false).setUpdateOperation(true).setListOperation(false) |
| 229 | 285 | .setListOperationResult(true) |
| 230 | 286 | .setId(200L); |
| 231 | - CodegenColumnDO addressDetailColumn = new CodegenColumnDO().setColumnName("detail").setDataType(JdbcType.VARCHAR.name()) | |
| 232 | - .setColumnComment("明细").setNullable(false).setPrimaryKey(false) | |
| 233 | - .setOrdinalPosition(3).setJavaType("String").setJavaField("detail").setExample("码头路 88 号") | |
| 234 | - .setCreateOperation(true).setUpdateOperation(true).setListOperation(true) | |
| 235 | - .setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition()).setListOperationResult(true) | |
| 236 | - .setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType()); | |
| 237 | - List<CodegenColumnDO> addressColumns = Arrays.asList(addressIdColumn, addressStudentColumn, addressDetailColumn); | |
| 287 | + List<CodegenColumnDO> addressColumns = Arrays.asList(addressIdColumn, addressStudentIdColumn); | |
| 238 | 288 | |
| 239 | 289 | // 调用 |
| 240 | 290 | Map<String, String> result = codegenEngine.execute(table, columns, |
| 241 | 291 | Arrays.asList(contactTable, addressTable), Arrays.asList(contactColumns, addressColumns)); |
| 242 | 292 | |
| 243 | 293 | // 断言 |
| 244 | - assertEquals(25, result.size()); | |
| 294 | + assertEquals(27, result.size()); | |
| 245 | 295 | |
| 246 | 296 | for (Map.Entry<String, String> entry : result.entrySet()) { |
| 247 | 297 | System.out.println(entry.getKey()); | ... | ... |