Commit 40d2882890f596d6e2b68ba5ca4c0db24622049f
1 parent
7d89ce5a
🎈 perf(codegen): 优化代码生成器 Excel 导入:新增 import-enable 开关,Vue3 / Vben5 Schema 抽独立 Im…
…portForm 组件对齐 user 模块,补齐 Vben5 4 套 frontType 单测与 importEnable=true 断言 基于 #1082 #1083 的二开
Showing
34 changed files
with
1123 additions
and
336 deletions
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/codegen/config/CodegenProperties.java
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
| ... | ... | @@ -128,6 +128,8 @@ public class CodegenEngine { |
| 128 | 128 | vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) |
| 129 | 129 | .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/form.vue"), |
| 130 | 130 | vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) |
| 131 | + .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/import.vue"), | |
| 132 | + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}ImportForm.vue")) | |
| 131 | 133 | .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑 |
| 132 | 134 | vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) |
| 133 | 135 | .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑 |
| ... | ... | @@ -166,6 +168,8 @@ public class CodegenEngine { |
| 166 | 168 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) |
| 167 | 169 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/form.vue"), |
| 168 | 170 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) |
| 171 | + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/import.vue"), | |
| 172 | + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) | |
| 169 | 173 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("api/api.ts"), |
| 170 | 174 | vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) |
| 171 | 175 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 |
| ... | ... | @@ -183,6 +187,8 @@ public class CodegenEngine { |
| 183 | 187 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) |
| 184 | 188 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/form.vue"), |
| 185 | 189 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) |
| 190 | + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/import.vue"), | |
| 191 | + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) | |
| 186 | 192 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("api/api.ts"), |
| 187 | 193 | vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) |
| 188 | 194 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 |
| ... | ... | @@ -202,6 +208,8 @@ public class CodegenEngine { |
| 202 | 208 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) |
| 203 | 209 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/form.vue"), |
| 204 | 210 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) |
| 211 | + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/import.vue"), | |
| 212 | + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) | |
| 205 | 213 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("api/api.ts"), |
| 206 | 214 | vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) |
| 207 | 215 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 |
| ... | ... | @@ -219,6 +227,8 @@ public class CodegenEngine { |
| 219 | 227 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) |
| 220 | 228 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/form.vue"), |
| 221 | 229 | vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) |
| 230 | + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/import.vue"), | |
| 231 | + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) | |
| 222 | 232 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("api/api.ts"), |
| 223 | 233 | vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) |
| 224 | 234 | .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 |
| ... | ... | @@ -286,6 +296,7 @@ public class CodegenEngine { |
| 286 | 296 | globalBindingMap.put("jakartaPackage", jakartaEnable ? "jakarta" : "javax"); |
| 287 | 297 | globalBindingMap.put("voType", codegenProperties.getVoType()); |
| 288 | 298 | globalBindingMap.put("deleteBatchEnable", codegenProperties.getDeleteBatchEnable()); |
| 299 | + globalBindingMap.put("importEnable", codegenProperties.getImportEnable()); | |
| 289 | 300 | // 全局 Java Bean |
| 290 | 301 | globalBindingMap.put("CommonResultClassName", CommonResult.class.getName()); |
| 291 | 302 | globalBindingMap.put("PageResultClassName", PageResult.class.getName()); |
| ... | ... | @@ -345,6 +356,11 @@ public class CodegenEngine { |
| 345 | 356 | if (!CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { |
| 346 | 357 | return; |
| 347 | 358 | } |
| 359 | + } else if (isImportTemplate(vmPath)) { | |
| 360 | + // 关闭 import 时,跳过 ImportExcelVO / ImportRespVO 的生成 | |
| 361 | + if (!Boolean.TRUE.equals(codegenProperties.getImportEnable())) { | |
| 362 | + return; | |
| 363 | + } | |
| 348 | 364 | } |
| 349 | 365 | // 2.3 默认生成 |
| 350 | 366 | generateCode(result, vmPath, filePath, bindingMap); |
| ... | ... | @@ -678,4 +694,9 @@ public class CodegenEngine { |
| 678 | 694 | return path.contains("listReqVO"); |
| 679 | 695 | } |
| 680 | 696 | |
| 697 | + private static boolean isImportTemplate(String path) { | |
| 698 | + return path.contains("importExcelVO") || path.contains("importRespVO") | |
| 699 | + || path.contains("views/import.vue"); | |
| 700 | + } | |
| 701 | + | |
| 681 | 702 | } | ... | ... |
yudao-module-infra/src/main/resources/codegen/java/controller/controller.vm
| 1 | 1 | package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}; |
| 2 | 2 | |
| 3 | 3 | import org.springframework.web.bind.annotation.*; |
| 4 | +#if ($importEnable) | |
| 4 | 5 | import org.springframework.web.multipart.MultipartFile; |
| 6 | +#end | |
| 5 | 7 | import ${jakartaPackage}.annotation.Resource; |
| 6 | 8 | import org.springframework.validation.annotation.Validated; |
| 7 | 9 | #if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end |
| ... | ... | @@ -160,13 +162,14 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { |
| 160 | 162 | BeanUtils.toBean(list, ${table.className}RespVO.class)); |
| 161 | 163 | } |
| 162 | 164 | #end |
| 165 | +#if ($importEnable) | |
| 163 | 166 | |
| 164 | 167 | @GetMapping("/get-import-template") |
| 165 | 168 | @Operation(summary = "获得导入${table.classComment}模板") |
| 166 | 169 | #if ($sceneEnum.scene == 1) |
| 167 | 170 | @PreAuthorize("@ss.hasPermission('${permissionPrefix}:import')") |
| 168 | 171 | #end |
| 169 | - public void import${simpleClassName}Template(HttpServletResponse response) throws IOException { | |
| 172 | + public void importTemplate(HttpServletResponse response) throws IOException { | |
| 170 | 173 | ExcelUtils.write(response, "${table.classComment}导入模板.xls", "数据", |
| 171 | 174 | ${sceneEnum.prefixClass}${table.className}ImportExcelVO.class, Collections.emptyList()); |
| 172 | 175 | } |
| ... | ... | @@ -177,11 +180,11 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { |
| 177 | 180 | #if ($sceneEnum.scene == 1) |
| 178 | 181 | @PreAuthorize("@ss.hasPermission('${permissionPrefix}:import')") |
| 179 | 182 | #end |
| 180 | - @ApiAccessLog(operateType = IMPORT) | |
| 181 | - public CommonResult<${sceneEnum.prefixClass}${table.className}ImportRespVO> import${simpleClassName}(@RequestParam("file") MultipartFile file) throws Exception { | |
| 183 | + public CommonResult<${sceneEnum.prefixClass}${table.className}ImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { | |
| 182 | 184 | List<${sceneEnum.prefixClass}${table.className}ImportExcelVO> list = ExcelUtils.read(file, ${sceneEnum.prefixClass}${table.className}ImportExcelVO.class); |
| 183 | 185 | return success(${classNameVar}Service.import${simpleClassName}List(list)); |
| 184 | 186 | } |
| 187 | +#end | |
| 185 | 188 | |
| 186 | 189 | ## 特殊:主子表专属逻辑 |
| 187 | 190 | #foreach ($subTable in $subTables) | ... | ... |
yudao-module-infra/src/main/resources/codegen/java/service/service.vm
| ... | ... | @@ -25,6 +25,7 @@ public interface ${table.className}Service { |
| 25 | 25 | * @return 编号 |
| 26 | 26 | */ |
| 27 | 27 | ${primaryColumn.javaType} create${simpleClassName}(@Valid ${saveReqVOClass} ${saveReqVOVar}); |
| 28 | +#if ($importEnable) | |
| 28 | 29 | |
| 29 | 30 | /** |
| 30 | 31 | * 导入${table.classComment} |
| ... | ... | @@ -33,6 +34,7 @@ public interface ${table.className}Service { |
| 33 | 34 | * @return 导入结果 |
| 34 | 35 | */ |
| 35 | 36 | ${sceneEnum.prefixClass}${table.className}ImportRespVO import${simpleClassName}List(List<${sceneEnum.prefixClass}${table.className}ImportExcelVO> importList); |
| 37 | +#end | |
| 36 | 38 | |
| 37 | 39 | /** |
| 38 | 40 | * 更新${table.classComment} | ... | ... |
yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm
| ... | ... | @@ -7,7 +7,9 @@ import org.springframework.validation.annotation.Validated; |
| 7 | 7 | import org.springframework.transaction.annotation.Transactional; |
| 8 | 8 | |
| 9 | 9 | import java.util.*; |
| 10 | +#if ($importEnable) | |
| 10 | 11 | import java.util.concurrent.atomic.AtomicInteger; |
| 12 | +#end | |
| 11 | 13 | import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; |
| 12 | 14 | import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; |
| 13 | 15 | ## 特殊:主子表专属逻辑 |
| ... | ... | @@ -92,46 +94,32 @@ public class ${table.className}ServiceImpl implements ${table.className}Service |
| 92 | 94 | // 返回 |
| 93 | 95 | return ${classNameVar}.getId(); |
| 94 | 96 | } |
| 97 | +#if ($importEnable) | |
| 95 | 98 | |
| 96 | 99 | @Override |
| 97 | - @Transactional(rollbackFor = Exception.class) | |
| 100 | + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 | |
| 98 | 101 | public ${sceneEnum.prefixClass}${table.className}ImportRespVO import${simpleClassName}List(List<${sceneEnum.prefixClass}${table.className}ImportExcelVO> importList) { |
| 99 | 102 | if (CollUtil.isEmpty(importList)) { |
| 100 | 103 | return ${sceneEnum.prefixClass}${table.className}ImportRespVO.builder() |
| 101 | - .successCount(0) | |
| 102 | - .failureCount(0) | |
| 103 | - .failureRows(new LinkedHashMap<>()) | |
| 104 | - .build(); | |
| 104 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 105 | 105 | } |
| 106 | - AtomicInteger successCount = new AtomicInteger(); | |
| 107 | - Map<Integer, String> failureRows = new LinkedHashMap<>(); | |
| 106 | + // 遍历,逐个创建 | |
| 107 | + ${sceneEnum.prefixClass}${table.className}ImportRespVO respVO = ${sceneEnum.prefixClass}${table.className}ImportRespVO.builder() | |
| 108 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 108 | 109 | AtomicInteger index = new AtomicInteger(1); |
| 109 | 110 | importList.forEach(importItem -> { |
| 110 | 111 | int currentIndex = index.getAndIncrement(); |
| 111 | 112 | try { |
| 112 | 113 | create${simpleClassName}(BeanUtils.toBean(importItem, ${saveReqVOClass}.class)); |
| 113 | - successCount.incrementAndGet(); | |
| 114 | + respVO.setSuccessCount(respVO.getSuccessCount() + 1); | |
| 114 | 115 | } catch (Exception ex) { |
| 115 | - failureRows.put(currentIndex, resolveImportFailureMessage(ex)); | |
| 116 | + respVO.getFailureRows().put(currentIndex, ex.getMessage()); | |
| 116 | 117 | } |
| 117 | 118 | }); |
| 118 | - return ${sceneEnum.prefixClass}${table.className}ImportRespVO.builder() | |
| 119 | - .successCount(successCount.get()) | |
| 120 | - .failureCount(failureRows.size()) | |
| 121 | - .failureRows(failureRows) | |
| 122 | - .build(); | |
| 123 | - } | |
| 124 | - | |
| 125 | - /** | |
| 126 | - * 仅返回根因异常信息,避免把 MyBatis 长堆栈直接暴露给前端。 | |
| 127 | - */ | |
| 128 | - private String resolveImportFailureMessage(Exception ex) { | |
| 129 | - Throwable root = ex; | |
| 130 | - while (root.getCause() != null && root.getCause() != root) { | |
| 131 | - root = root.getCause(); | |
| 132 | - } | |
| 133 | - return root.getMessage() != null ? root.getMessage() : ex.getMessage(); | |
| 119 | + respVO.setFailureCount(respVO.getFailureRows().size()); | |
| 120 | + return respVO; | |
| 134 | 121 | } |
| 122 | +#end | |
| 135 | 123 | |
| 136 | 124 | @Override |
| 137 | 125 | ## 特殊:主子表专属逻辑(非 ERP 模式) | ... | ... |
yudao-module-infra/src/main/resources/codegen/sql/sql.vm
| 1 | 1 | ## 通用变量定义 |
| 2 | +#if ($importEnable) | |
| 2 | 3 | #set ($functionNames = ['查询', '创建', '更新', '删除', '导出', '导入']) |
| 3 | 4 | #set ($functionOps = ['query', 'create', 'update', 'delete', 'export', 'import']) |
| 5 | +#else | |
| 6 | +#set ($functionNames = ['查询', '创建', '更新', '删除', '导出']) | |
| 7 | +#set ($functionOps = ['query', 'create', 'update', 'delete', 'export']) | |
| 8 | +#end | |
| 4 | 9 | ## |
| 5 | 10 | ## 宏定义:生成按钮 SQL(通用部分) |
| 6 | 11 | #macro(insertButtonSql $parentIdVar) | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue/api/api.js.vm
| ... | ... | @@ -73,6 +73,7 @@ export function export${simpleClassName}Excel(params) { |
| 73 | 73 | responseType: 'blob' |
| 74 | 74 | }) |
| 75 | 75 | } |
| 76 | +#if ($importEnable) | |
| 76 | 77 | |
| 77 | 78 | // 下载${table.classComment}导入模板 |
| 78 | 79 | export function import${simpleClassName}Template() { |
| ... | ... | @@ -91,6 +92,7 @@ export function import${simpleClassName}(data) { |
| 91 | 92 | data |
| 92 | 93 | }) |
| 93 | 94 | } |
| 95 | +#end | |
| 94 | 96 | ## 特殊:主子表专属逻辑 |
| 95 | 97 | #foreach ($subTable in $subTables) |
| 96 | 98 | #set ($index = $foreach.count - 1) | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm
| ... | ... | @@ -49,6 +49,7 @@ |
| 49 | 49 | <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openForm(undefined)" |
| 50 | 50 | v-hasPermi="['${permissionPrefix}:create']">新增</el-button> |
| 51 | 51 | </el-col> |
| 52 | +#if ($importEnable) | |
| 52 | 53 | <el-col :span="1.5"> |
| 53 | 54 | <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" |
| 54 | 55 | :loading="importLoading" v-hasPermi="['${permissionPrefix}:import']">导入</el-button> |
| ... | ... | @@ -57,6 +58,7 @@ |
| 57 | 58 | <el-button type="info" plain icon="el-icon-document" size="mini" @click="handleImportTemplate" |
| 58 | 59 | v-hasPermi="['${permissionPrefix}:import']">导入模板</el-button> |
| 59 | 60 | </el-col> |
| 61 | +#end | |
| 60 | 62 | <el-col :span="1.5"> |
| 61 | 63 | <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading" |
| 62 | 64 | v-hasPermi="['${permissionPrefix}:export']">导出</el-button> |
| ... | ... | @@ -86,7 +88,9 @@ |
| 86 | 88 | #end |
| 87 | 89 | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| 88 | 90 | </el-row> |
| 91 | +#if ($importEnable) | |
| 89 | 92 | <input ref="importFileRef" type="file" style="display: none" accept=".xls,.xlsx" @change="handleImportFileChange" /> |
| 93 | +#end | |
| 90 | 94 | |
| 91 | 95 | ## 特殊:主子表专属逻辑 |
| 92 | 96 | #if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 ) |
| ... | ... | @@ -253,8 +257,10 @@ export default { |
| 253 | 257 | loading: true, |
| 254 | 258 | // 导出遮罩层 |
| 255 | 259 | exportLoading: false, |
| 260 | +#if ($importEnable) | |
| 256 | 261 | // 导入遮罩层 |
| 257 | 262 | importLoading: false, |
| 263 | +#end | |
| 258 | 264 | // 显示搜索条件 |
| 259 | 265 | showSearch: true, |
| 260 | 266 | ## 特殊:树表专属逻辑(树不需要分页接口) |
| ... | ... | @@ -333,6 +339,7 @@ export default { |
| 333 | 339 | openForm(id) { |
| 334 | 340 | this.#[[$]]#refs["formRef"].open(id); |
| 335 | 341 | }, |
| 342 | +#if ($importEnable) | |
| 336 | 343 | /** 导入按钮操作 */ |
| 337 | 344 | handleImport() { |
| 338 | 345 | this.$refs.importFileRef && this.$refs.importFileRef.click(); |
| ... | ... | @@ -369,6 +376,7 @@ export default { |
| 369 | 376 | this.importLoading = false; |
| 370 | 377 | } |
| 371 | 378 | }, |
| 379 | +#end | |
| 372 | 380 | /** 删除按钮操作 */ |
| 373 | 381 | async handleDelete(row) { |
| 374 | 382 | const ${primaryColumn.javaField} = row.${primaryColumn.javaField}; | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3/api/api.ts.vm
| ... | ... | @@ -98,6 +98,7 @@ export const ${simpleClassName}Api = { |
| 98 | 98 | export${simpleClassName}: async (params) => { |
| 99 | 99 | return await request.download({ url: `${baseURL}/export-excel`, params }) |
| 100 | 100 | }, |
| 101 | +#if ($importEnable) | |
| 101 | 102 | |
| 102 | 103 | // 下载${table.classComment}导入模板 |
| 103 | 104 | import${simpleClassName}Template: async () => { |
| ... | ... | @@ -108,6 +109,7 @@ export const ${simpleClassName}Api = { |
| 108 | 109 | import${simpleClassName}: async (data: FormData) => { |
| 109 | 110 | return await request.upload({ url: `${baseURL}/import`, data }) |
| 110 | 111 | }, |
| 112 | +#end | |
| 111 | 113 | ## 特殊:主子表专属逻辑 |
| 112 | 114 | #foreach ($subTable in $subTables) |
| 113 | 115 | #set ($index = $foreach.count - 1) | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3/views/import.vue.vm
0 → 100644
| 1 | +<template> | |
| 2 | + <Dialog v-model="dialogVisible" title="${table.classComment}导入" width="400"> | |
| 3 | + <el-upload | |
| 4 | + ref="uploadRef" | |
| 5 | + v-model:file-list="fileList" | |
| 6 | + :auto-upload="false" | |
| 7 | + :disabled="formLoading" | |
| 8 | + :limit="1" | |
| 9 | + :on-exceed="handleExceed" | |
| 10 | + accept=".xlsx, .xls" | |
| 11 | + action="none" | |
| 12 | + drag | |
| 13 | + > | |
| 14 | + <Icon icon="ep:upload" /> | |
| 15 | + <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> | |
| 16 | + <template #tip> | |
| 17 | + <div class="el-upload__tip text-center"> | |
| 18 | + <span>仅允许导入 xls、xlsx 格式文件。</span> | |
| 19 | + <el-link | |
| 20 | + :underline="false" | |
| 21 | + style="font-size: 12px; vertical-align: baseline" | |
| 22 | + type="primary" | |
| 23 | + @click="handleDownloadTemplate" | |
| 24 | + > | |
| 25 | + 下载模板 | |
| 26 | + </el-link> | |
| 27 | + </div> | |
| 28 | + </template> | |
| 29 | + </el-upload> | |
| 30 | + <template #footer> | |
| 31 | + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> | |
| 32 | + <el-button @click="dialogVisible = false">取 消</el-button> | |
| 33 | + </template> | |
| 34 | + </Dialog> | |
| 35 | +</template> | |
| 36 | +<script setup lang="ts"> | |
| 37 | +import type { UploadUserFile } from 'element-plus' | |
| 38 | +import download from '@/utils/download' | |
| 39 | +import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}' | |
| 40 | + | |
| 41 | +/** ${table.classComment} 导入 */ | |
| 42 | +defineOptions({ name: '${simpleClassName}ImportForm' }) | |
| 43 | + | |
| 44 | +const message = useMessage() // 消息弹窗 | |
| 45 | + | |
| 46 | +const dialogVisible = ref(false) // 弹窗的是否展示 | |
| 47 | +const formLoading = ref(false) // 表单的加载中:上传、下载模板 | |
| 48 | +const uploadRef = ref() | |
| 49 | +const fileList = ref<UploadUserFile[]>([]) | |
| 50 | + | |
| 51 | +/** 打开弹窗 */ | |
| 52 | +const open = async () => { | |
| 53 | + dialogVisible.value = true | |
| 54 | + await resetForm() | |
| 55 | +} | |
| 56 | +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 | |
| 57 | + | |
| 58 | +/** 提交导入 */ | |
| 59 | +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 | |
| 60 | +const submitForm = async () => { | |
| 61 | + if (fileList.value.length === 0) { | |
| 62 | + message.error('请上传文件') | |
| 63 | + return | |
| 64 | + } | |
| 65 | + formLoading.value = true | |
| 66 | + try { | |
| 67 | + const formData = new FormData() | |
| 68 | + formData.append('file', fileList.value[0].raw as Blob) | |
| 69 | + const res = await ${simpleClassName}Api.import${simpleClassName}(formData) | |
| 70 | + const data = res.data | |
| 71 | + let text = '导入成功数量:' + data.successCount + ';导入失败数量:' + data.failureCount + ';' | |
| 72 | + if (data.failureCount > 0) { | |
| 73 | + for (const rowNo in data.failureRows) { | |
| 74 | + text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >' | |
| 75 | + } | |
| 76 | + } | |
| 77 | + message.alert(text) | |
| 78 | + dialogVisible.value = false | |
| 79 | + emit('success') | |
| 80 | + } finally { | |
| 81 | + formLoading.value = false | |
| 82 | + await resetForm() | |
| 83 | + } | |
| 84 | +} | |
| 85 | + | |
| 86 | +/** 下载导入模板 */ | |
| 87 | +const handleDownloadTemplate = async () => { | |
| 88 | + const data = await ${simpleClassName}Api.import${simpleClassName}Template() | |
| 89 | + download.excel(data, '${table.classComment}导入模板.xls') | |
| 90 | +} | |
| 91 | + | |
| 92 | +/** 文件超限 */ | |
| 93 | +const handleExceed = (): void => { | |
| 94 | + message.error('最多只能上传一个文件!') | |
| 95 | +} | |
| 96 | + | |
| 97 | +/** 重置表单 */ | |
| 98 | +const resetForm = async () => { | |
| 99 | + fileList.value = [] | |
| 100 | + await nextTick() | |
| 101 | + uploadRef.value?.clearFiles() | |
| 102 | +} | |
| 103 | +</script> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm
| ... | ... | @@ -92,6 +92,7 @@ |
| 92 | 92 | > |
| 93 | 93 | <Icon icon="ep:plus" class="mr-5px" /> 新增 |
| 94 | 94 | </el-button> |
| 95 | +#if ($importEnable) | |
| 95 | 96 | <el-button |
| 96 | 97 | type="warning" |
| 97 | 98 | plain |
| ... | ... | @@ -100,6 +101,7 @@ |
| 100 | 101 | > |
| 101 | 102 | <Icon icon="ep:upload" class="mr-5px" /> 导入 |
| 102 | 103 | </el-button> |
| 104 | +#end | |
| 103 | 105 | <el-button |
| 104 | 106 | type="success" |
| 105 | 107 | plain |
| ... | ... | @@ -245,43 +247,11 @@ |
| 245 | 247 | @pagination="getList" |
| 246 | 248 | /> |
| 247 | 249 | </ContentWrap> |
| 250 | +#if ($importEnable) | |
| 248 | 251 | |
| 249 | 252 | <!-- 导入弹窗 --> |
| 250 | - <Dialog v-model="importDialogVisible" title="${table.classComment}导入" width="400"> | |
| 251 | - <el-upload | |
| 252 | - ref="uploadRef" | |
| 253 | - v-model:file-list="fileList" | |
| 254 | - :auto-upload="false" | |
| 255 | - :disabled="importFormLoading" | |
| 256 | - :limit="1" | |
| 257 | - :on-exceed="handleImportExceed" | |
| 258 | - accept=".xlsx, .xls" | |
| 259 | - action="none" | |
| 260 | - drag | |
| 261 | - > | |
| 262 | - <Icon icon="ep:upload" /> | |
| 263 | - <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> | |
| 264 | - <template #tip> | |
| 265 | - <div class="el-upload__tip text-center"> | |
| 266 | - <span>仅允许导入 xls、xlsx 格式文件。</span> | |
| 267 | - <el-link | |
| 268 | - :underline="false" | |
| 269 | - style="font-size: 12px; vertical-align: baseline" | |
| 270 | - type="primary" | |
| 271 | - @click="handleImportTemplate" | |
| 272 | - > | |
| 273 | - 下载模板 | |
| 274 | - </el-link> | |
| 275 | - </div> | |
| 276 | - </template> | |
| 277 | - </el-upload> | |
| 278 | - <template #footer> | |
| 279 | - <el-button :disabled="importFormLoading" type="primary" @click="submitImportForm"> | |
| 280 | - 确 定 | |
| 281 | - </el-button> | |
| 282 | - <el-button @click="importDialogVisible = false">取 消</el-button> | |
| 283 | - </template> | |
| 284 | - </Dialog> | |
| 253 | + <${simpleClassName}ImportForm ref="importRef" @success="getList" /> | |
| 254 | +#end | |
| 285 | 255 | |
| 286 | 256 | <!-- 表单弹窗:添加/修改 --> |
| 287 | 257 | <${simpleClassName}Form ref="formRef" @success="getList" /> |
| ... | ... | @@ -308,7 +278,9 @@ |
| 308 | 278 | import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' |
| 309 | 279 | import { isEmpty } from '@/utils/is' |
| 310 | 280 | import { dateFormatter } from '@/utils/formatTime' |
| 311 | -import type { UploadUserFile } from 'element-plus' | |
| 281 | +#if ($importEnable) | |
| 282 | +import ${simpleClassName}ImportForm from './${simpleClassName}ImportForm.vue' | |
| 283 | +#end | |
| 312 | 284 | ## 特殊:树表专属逻辑 |
| 313 | 285 | #if ( $table.templateType == 2 ) |
| 314 | 286 | import { handleTree } from '@/utils/tree' |
| ... | ... | @@ -354,10 +326,9 @@ const queryParams = reactive({ |
| 354 | 326 | }) |
| 355 | 327 | const queryFormRef = ref() // 搜索的表单 |
| 356 | 328 | const exportLoading = ref(false) // 导出的加载中 |
| 357 | -const importDialogVisible = ref(false) // 导入弹窗 | |
| 358 | -const importFormLoading = ref(false) // 导入的加载中 | |
| 359 | -const uploadRef = ref() | |
| 360 | -const fileList = ref<UploadUserFile[]>([]) | |
| 329 | +#if ($importEnable) | |
| 330 | +const importRef = ref() // ${table.classComment} 导入组件的 Ref | |
| 331 | +#end | |
| 361 | 332 | |
| 362 | 333 | /** 查询列表 */ |
| 363 | 334 | const getList = async () => { |
| ... | ... | @@ -394,58 +365,13 @@ const formRef = ref() |
| 394 | 365 | const openForm = (type: string, id?: number) => { |
| 395 | 366 | formRef.value.open(type, id) |
| 396 | 367 | } |
| 368 | +#if ($importEnable) | |
| 397 | 369 | |
| 398 | 370 | /** 导入按钮操作 */ |
| 399 | -const handleImport = async () => { | |
| 400 | - importDialogVisible.value = true | |
| 401 | - await resetImportForm() | |
| 402 | -} | |
| 403 | - | |
| 404 | -/** 提交导入 */ | |
| 405 | -const submitImportForm = async () => { | |
| 406 | - if (fileList.value.length === 0) { | |
| 407 | - message.error('请上传文件') | |
| 408 | - return | |
| 409 | - } | |
| 410 | - importFormLoading.value = true | |
| 411 | - try { | |
| 412 | - const formData = new FormData() | |
| 413 | - formData.append('file', fileList.value[0].raw as Blob) | |
| 414 | - const res = await ${simpleClassName}Api.import${simpleClassName}(formData) | |
| 415 | - const data = res.data | |
| 416 | - let text = '导入成功数量:' + data.successCount + ';导入失败数量:' + data.failureCount + ';' | |
| 417 | - if (data.failureCount > 0) { | |
| 418 | - for (const rowNo in data.failureRows) { | |
| 419 | - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >' | |
| 420 | - } | |
| 421 | - } | |
| 422 | - message.alert(text) | |
| 423 | - importDialogVisible.value = false | |
| 424 | - await getList() | |
| 425 | - } catch { | |
| 426 | - } finally { | |
| 427 | - importFormLoading.value = false | |
| 428 | - await resetImportForm() | |
| 429 | - } | |
| 430 | -} | |
| 431 | - | |
| 432 | -/** 下载导入模板 */ | |
| 433 | -const handleImportTemplate = async () => { | |
| 434 | - const data = await ${simpleClassName}Api.import${simpleClassName}Template() | |
| 435 | - download.excel(data, '${table.classComment}导入模板.xls') | |
| 436 | -} | |
| 437 | - | |
| 438 | -/** 导入文件超限 */ | |
| 439 | -const handleImportExceed = (): void => { | |
| 440 | - message.error('最多只能上传一个文件!') | |
| 441 | -} | |
| 442 | - | |
| 443 | -/** 重置导入表单 */ | |
| 444 | -const resetImportForm = async () => { | |
| 445 | - fileList.value = [] | |
| 446 | - await nextTick() | |
| 447 | - uploadRef.value?.clearFiles() | |
| 371 | +const handleImport = () => { | |
| 372 | + importRef.value.open() | |
| 448 | 373 | } |
| 374 | +#end | |
| 449 | 375 | |
| 450 | 376 | /** 删除按钮操作 */ |
| 451 | 377 | const handleDelete = async (id: number) => { | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben/api/api.ts.vm
| ... | ... | @@ -30,6 +30,7 @@ export function delete${simpleClassName}(id: number) { |
| 30 | 30 | export function export${simpleClassName}(params) { |
| 31 | 31 | return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls') |
| 32 | 32 | } |
| 33 | +#if ($importEnable) | |
| 33 | 34 | |
| 34 | 35 | // 下载${table.classComment}导入模板 |
| 35 | 36 | export function import${simpleClassName}Template() { |
| ... | ... | @@ -40,3 +41,4 @@ export function import${simpleClassName}Template() { |
| 40 | 41 | export function import${simpleClassName}(data: FormData) { |
| 41 | 42 | return defHttp.post({ url: '${baseURL}/import', data }) |
| 42 | 43 | } |
| 44 | +#end | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben/views/index.vue.vm
| ... | ... | @@ -11,8 +11,10 @@ import { |
| 11 | 11 | delete${simpleClassName}, |
| 12 | 12 | export${simpleClassName}, |
| 13 | 13 | get${simpleClassName}Page, |
| 14 | +#if ($importEnable) | |
| 14 | 15 | import${simpleClassName}, |
| 15 | 16 | import${simpleClassName}Template, |
| 17 | +#end | |
| 16 | 18 | } from '@/api/${table.moduleName}/${table.businessName}' |
| 17 | 19 | |
| 18 | 20 | defineOptions({ name: '${table.className}' }) |
| ... | ... | @@ -20,8 +22,10 @@ defineOptions({ name: '${table.className}' }) |
| 20 | 22 | const { t } = useI18n() |
| 21 | 23 | const { createConfirm, createMessage } = useMessage() |
| 22 | 24 | const [registerModal, { openModal }] = useModal() |
| 25 | +#if ($importEnable) | |
| 23 | 26 | const importFileRef = ref<HTMLInputElement>() |
| 24 | 27 | const importLoading = ref(false) |
| 28 | +#end | |
| 25 | 29 | |
| 26 | 30 | const [registerTable, { getForm, reload }] = useTable({ |
| 27 | 31 | title: '${table.classComment}列表', |
| ... | ... | @@ -57,6 +61,7 @@ async function handleExport() { |
| 57 | 61 | }, |
| 58 | 62 | }) |
| 59 | 63 | } |
| 64 | +#if ($importEnable) | |
| 60 | 65 | |
| 61 | 66 | function handleImport() { |
| 62 | 67 | importFileRef.value?.click() |
| ... | ... | @@ -93,6 +98,7 @@ async function handleImportFileChange(event: Event) { |
| 93 | 98 | importLoading.value = false |
| 94 | 99 | } |
| 95 | 100 | } |
| 101 | +#end | |
| 96 | 102 | |
| 97 | 103 | async function handleDelete(record: Recordable) { |
| 98 | 104 | await delete${simpleClassName}(record.id) |
| ... | ... | @@ -107,12 +113,14 @@ async function handleDelete(record: Recordable) { |
| 107 | 113 | <a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate"> |
| 108 | 114 | {{ t('action.create') }} |
| 109 | 115 | </a-button> |
| 116 | +#if ($importEnable) | |
| 110 | 117 | <a-button v-auth="['${permissionPrefix}:import']" :loading="importLoading" @click="handleImport"> |
| 111 | 118 | 导入 |
| 112 | 119 | </a-button> |
| 113 | 120 | <a-button v-auth="['${permissionPrefix}:import']" @click="handleImportTemplateDownload"> |
| 114 | 121 | 导入模板 |
| 115 | 122 | </a-button> |
| 123 | +#end | |
| 116 | 124 | <a-button v-auth="['${permissionPrefix}:export']" :preIcon="IconEnum.EXPORT" @click="handleExport"> |
| 117 | 125 | {{ t('action.export') }} |
| 118 | 126 | </a-button> |
| ... | ... | @@ -138,7 +146,9 @@ async function handleDelete(record: Recordable) { |
| 138 | 146 | </template> |
| 139 | 147 | </template> |
| 140 | 148 | </BasicTable> |
| 149 | +#if ($importEnable) | |
| 141 | 150 | <input ref="importFileRef" type="file" accept=".xls,.xlsx" class="hidden" @change="handleImportFileChange" /> |
| 151 | +#end | |
| 142 | 152 | <${simpleClassName}Modal @register="registerModal" @success="reload()" /> |
| 143 | 153 | </div> |
| 144 | 154 | </template> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/api/api.ts.vm
| ... | ... | @@ -100,6 +100,7 @@ export function delete${simpleClassName}List(ids: number[]) { |
| 100 | 100 | export function export${simpleClassName}(params: any) { |
| 101 | 101 | return requestClient.download('${baseURL}/export-excel', { params }); |
| 102 | 102 | } |
| 103 | +#if ($importEnable) | |
| 103 | 104 | |
| 104 | 105 | /** 下载${table.classComment}导入模板 */ |
| 105 | 106 | export function import${simpleClassName}Template() { |
| ... | ... | @@ -110,6 +111,7 @@ export function import${simpleClassName}Template() { |
| 110 | 111 | export function import${simpleClassName}(data: FormData) { |
| 111 | 112 | return requestClient.post('${baseURL}/import', data); |
| 112 | 113 | } |
| 114 | +#end | |
| 113 | 115 | |
| 114 | 116 | ## 特殊:主子表专属逻辑 |
| 115 | 117 | #foreach ($subTable in $subTables) | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/import.vue.vm
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { FileType } from 'ant-design-vue/es/upload/interface'; | |
| 3 | + | |
| 4 | +import { ref } from 'vue'; | |
| 5 | + | |
| 6 | +import { useVbenModal } from '@vben/common-ui'; | |
| 7 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 8 | + | |
| 9 | +import { Button, message, Upload } from 'ant-design-vue'; | |
| 10 | + | |
| 11 | +import { import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 12 | + | |
| 13 | +defineOptions({ name: '${simpleClassName}Import' }); | |
| 14 | + | |
| 15 | +const emit = defineEmits(['success']); | |
| 16 | +const fileRef = ref<File | null>(null); | |
| 17 | + | |
| 18 | +const [Modal, modalApi] = useVbenModal({ | |
| 19 | + async onConfirm() { | |
| 20 | + if (!fileRef.value) { | |
| 21 | + message.error('请上传文件'); | |
| 22 | + return; | |
| 23 | + } | |
| 24 | + modalApi.lock(); | |
| 25 | + try { | |
| 26 | + const formData = new FormData(); | |
| 27 | + formData.append('file', fileRef.value); | |
| 28 | + const response: any = await import${simpleClassName}(formData); | |
| 29 | + const data = response?.data ?? response ?? {}; | |
| 30 | + let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 31 | + if (data.failureRows) { | |
| 32 | + Object.keys(data.failureRows).forEach((rowNo) => { | |
| 33 | + text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 34 | + }); | |
| 35 | + } | |
| 36 | + message.info(text); | |
| 37 | + await modalApi.close(); | |
| 38 | + emit('success'); | |
| 39 | + } finally { | |
| 40 | + modalApi.unlock(); | |
| 41 | + } | |
| 42 | + }, | |
| 43 | +}); | |
| 44 | + | |
| 45 | +/** 上传前:拦截 antd Upload 的自动上传,文件存到 ref */ | |
| 46 | +function beforeUpload(file: FileType) { | |
| 47 | + fileRef.value = file as unknown as File; | |
| 48 | + return false; | |
| 49 | +} | |
| 50 | + | |
| 51 | +/** 下载导入模板 */ | |
| 52 | +async function handleDownload() { | |
| 53 | + const data = await import${simpleClassName}Template(); | |
| 54 | + downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 55 | +} | |
| 56 | +</script> | |
| 57 | + | |
| 58 | +<template> | |
| 59 | + <Modal title="导入${table.classComment}" class="w-1/3"> | |
| 60 | + <div class="mx-4"> | |
| 61 | + <Upload :max-count="1" accept=".xls,.xlsx" :before-upload="beforeUpload"> | |
| 62 | + <Button type="primary"> 选择 Excel 文件 </Button> | |
| 63 | + </Upload> | |
| 64 | + </div> | |
| 65 | + <template #prepend-footer> | |
| 66 | + <div class="flex flex-auto items-center"> | |
| 67 | + <Button @click="handleDownload"> 下载导入模板 </Button> | |
| 68 | + </div> | |
| 69 | + </template> | |
| 70 | + </Modal> | |
| 71 | +</template> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm
| ... | ... | @@ -27,9 +27,12 @@ import { getRangePickerDefaultProps } from '#/utils/rangePickerProps'; |
| 27 | 27 | import { $t } from '#/locales'; |
| 28 | 28 | #if (${table.templateType} == 2)## 树表接口 |
| 29 | 29 | import { handleTree } from '@vben/utils' |
| 30 | -import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName}, import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 30 | +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 31 | 31 | #else## 标准表接口 |
| 32 | -import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName}, import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 32 | +import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 33 | +#end | |
| 34 | +#if ($importEnable) | |
| 35 | +import ${simpleClassName}Import from './modules/import-form.vue'; | |
| 33 | 36 | #end |
| 34 | 37 | |
| 35 | 38 | #if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况 |
| ... | ... | @@ -73,8 +76,6 @@ const queryParams = reactive({ |
| 73 | 76 | }) |
| 74 | 77 | const queryFormRef = ref() // 搜索的表单 |
| 75 | 78 | const exportLoading = ref(false) // 导出的加载中 |
| 76 | -const importLoading = ref(false) // 导入的加载中 | |
| 77 | -const importFileRef = ref<HTMLInputElement>() | |
| 78 | 79 | |
| 79 | 80 | /** 查询列表 */ |
| 80 | 81 | async function getList() { |
| ... | ... | @@ -121,6 +122,17 @@ const [FormModal, formModalApi] = useVbenModal({ |
| 121 | 122 | connectedComponent: ${simpleClassName}Form, |
| 122 | 123 | destroyOnClose: true, |
| 123 | 124 | }); |
| 125 | +#if ($importEnable) | |
| 126 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 127 | + connectedComponent: ${simpleClassName}Import, | |
| 128 | + destroyOnClose: true, | |
| 129 | +}); | |
| 130 | + | |
| 131 | +/** 导入${table.classComment} */ | |
| 132 | +function handleImport() { | |
| 133 | + importFormModalApi.open(); | |
| 134 | +} | |
| 135 | +#end | |
| 124 | 136 | |
| 125 | 137 | /** 创建${table.classComment} */ |
| 126 | 138 | function handleCreate() { |
| ... | ... | @@ -192,43 +204,6 @@ try { |
| 192 | 204 | } |
| 193 | 205 | } |
| 194 | 206 | |
| 195 | -/** 导入模板下载 */ | |
| 196 | -async function handleImportTemplateDownload() { | |
| 197 | - const data = await import${simpleClassName}Template(); | |
| 198 | - downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 199 | -} | |
| 200 | - | |
| 201 | -/** 导入按钮操作 */ | |
| 202 | -function handleImport() { | |
| 203 | - importFileRef.value?.click(); | |
| 204 | -} | |
| 205 | - | |
| 206 | -/** 导入文件变更 */ | |
| 207 | -async function handleImportFileChange(event: Event) { | |
| 208 | - const target = event.target as HTMLInputElement; | |
| 209 | - const file = target.files?.[0]; | |
| 210 | - if (!file) { | |
| 211 | - return; | |
| 212 | - } | |
| 213 | - importLoading.value = true; | |
| 214 | - try { | |
| 215 | - const formData = new FormData(); | |
| 216 | - formData.append('file', file); | |
| 217 | - const response: any = await import${simpleClassName}(formData); | |
| 218 | - const data = response?.data ?? response ?? {}; | |
| 219 | - let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 220 | - if (data.failureRows) { | |
| 221 | - Object.keys(data.failureRows).forEach((rowNo) => { | |
| 222 | - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 223 | - }); | |
| 224 | - } | |
| 225 | - message.info(text); | |
| 226 | - await getList(); | |
| 227 | - } finally { | |
| 228 | - target.value = ''; | |
| 229 | - importLoading.value = false; | |
| 230 | - } | |
| 231 | -} | |
| 232 | 207 | |
| 233 | 208 | #if (${table.templateType} == 2) |
| 234 | 209 | /** 切换树形展开/收缩状态 */ |
| ... | ... | @@ -249,7 +224,9 @@ onMounted(() => { |
| 249 | 224 | <template> |
| 250 | 225 | <Page auto-content-height> |
| 251 | 226 | <FormModal @success="getList" /> |
| 252 | - <input ref="importFileRef" type="file" accept=".xls,.xlsx" class="hidden" @change="handleImportFileChange" /> | |
| 227 | +#if ($importEnable) | |
| 228 | + <ImportFormModal @success="getList" /> | |
| 229 | +#end | |
| 253 | 230 | |
| 254 | 231 | <Card v-if="!hiddenSearchBar" class="mb-4"> |
| 255 | 232 | <!-- 搜索工作栏 --> |
| ... | ... | @@ -355,23 +332,16 @@ onMounted(() => { |
| 355 | 332 | > |
| 356 | 333 | {{ $t('ui.actionTitle.create', ['${table.classComment}']) }} |
| 357 | 334 | </Button> |
| 335 | +#if ($importEnable) | |
| 358 | 336 | <Button |
| 359 | 337 | class="ml-2" |
| 360 | 338 | type="primary" |
| 361 | - :loading="importLoading" | |
| 362 | 339 | @click="handleImport" |
| 363 | 340 | v-access:code="['${permissionPrefix}:import']" |
| 364 | 341 | > |
| 365 | 342 | 导入 |
| 366 | 343 | </Button> |
| 367 | - <Button | |
| 368 | - class="ml-2" | |
| 369 | - type="primary" | |
| 370 | - @click="handleImportTemplateDownload" | |
| 371 | - v-access:code="['${permissionPrefix}:import']" | |
| 372 | - > | |
| 373 | - 导入模板 | |
| 374 | - </Button> | |
| 344 | +#end | |
| 375 | 345 | <Button |
| 376 | 346 | :icon="h(Download)" |
| 377 | 347 | type="primary" | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm
| ... | ... | @@ -134,6 +134,21 @@ export function useFormSchema(): VbenFormSchema[] { |
| 134 | 134 | ]; |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | +#if ($importEnable) | |
| 138 | +/** 导入的表单 */ | |
| 139 | +export function useImportFormSchema(): VbenFormSchema[] { | |
| 140 | + return [ | |
| 141 | + { | |
| 142 | + fieldName: 'file', | |
| 143 | + label: '${table.classComment}数据', | |
| 144 | + component: 'Upload', | |
| 145 | + rules: 'required', | |
| 146 | + help: '仅允许导入 xls、xlsx 格式文件', | |
| 147 | + }, | |
| 148 | + ]; | |
| 149 | +} | |
| 150 | + | |
| 151 | +#end | |
| 137 | 152 | /** 列表的搜索表单 */ |
| 138 | 153 | export function useGridFormSchema(): VbenFormSchema[] { |
| 139 | 154 | return [ | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/import.vue.vm
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { FileType } from 'ant-design-vue/es/upload/interface'; | |
| 3 | + | |
| 4 | +import { useVbenModal } from '@vben/common-ui'; | |
| 5 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 6 | + | |
| 7 | +import { Button, message, Upload } from 'ant-design-vue'; | |
| 8 | + | |
| 9 | +import { useVbenForm } from '#/adapter/form'; | |
| 10 | +import { import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 11 | +import { $t } from '#/locales'; | |
| 12 | + | |
| 13 | +import { useImportFormSchema } from '../data'; | |
| 14 | + | |
| 15 | +const emit = defineEmits(['success']); | |
| 16 | + | |
| 17 | +const [Form, formApi] = useVbenForm({ | |
| 18 | + commonConfig: { | |
| 19 | + formItemClass: 'col-span-2', | |
| 20 | + labelWidth: 120, | |
| 21 | + }, | |
| 22 | + layout: 'horizontal', | |
| 23 | + schema: useImportFormSchema(), | |
| 24 | + showDefaultActions: false, | |
| 25 | +}); | |
| 26 | + | |
| 27 | +const [Modal, modalApi] = useVbenModal({ | |
| 28 | + async onConfirm() { | |
| 29 | + const { valid } = await formApi.validate(); | |
| 30 | + if (!valid) { | |
| 31 | + return; | |
| 32 | + } | |
| 33 | + modalApi.lock(); | |
| 34 | + // 提交表单 | |
| 35 | + const data = await formApi.getValues(); | |
| 36 | + try { | |
| 37 | + await import${simpleClassName}(data.file); | |
| 38 | + // 关闭并提示 | |
| 39 | + await modalApi.close(); | |
| 40 | + emit('success'); | |
| 41 | + message.success($t('ui.actionMessage.operationSuccess')); | |
| 42 | + } finally { | |
| 43 | + modalApi.unlock(); | |
| 44 | + } | |
| 45 | + }, | |
| 46 | +}); | |
| 47 | + | |
| 48 | +/** 上传前 */ | |
| 49 | +function beforeUpload(file: FileType) { | |
| 50 | + formApi.setFieldValue('file', file); | |
| 51 | + return false; | |
| 52 | +} | |
| 53 | + | |
| 54 | +/** 下载模板 */ | |
| 55 | +async function handleDownload() { | |
| 56 | + const data = await import${simpleClassName}Template(); | |
| 57 | + downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 58 | +} | |
| 59 | +</script> | |
| 60 | + | |
| 61 | +<template> | |
| 62 | + <Modal title="导入${table.classComment}" class="w-1/3"> | |
| 63 | + <Form class="mx-4"> | |
| 64 | + <template #file> | |
| 65 | + <div class="w-full"> | |
| 66 | + <Upload | |
| 67 | + :max-count="1" | |
| 68 | + accept=".xls,.xlsx" | |
| 69 | + :before-upload="beforeUpload" | |
| 70 | + > | |
| 71 | + <Button type="primary"> 选择 Excel 文件 </Button> | |
| 72 | + </Upload> | |
| 73 | + </div> | |
| 74 | + </template> | |
| 75 | + </Form> | |
| 76 | + <template #prepend-footer> | |
| 77 | + <div class="flex flex-auto items-center"> | |
| 78 | + <Button @click="handleDownload"> 下载导入模板 </Button> | |
| 79 | + </div> | |
| 80 | + </template> | |
| 81 | + </Modal> | |
| 82 | +</template> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm
| ... | ... | @@ -16,8 +16,6 @@ import { |
| 16 | 16 | delete${simpleClassName}, |
| 17 | 17 | export${simpleClassName}, |
| 18 | 18 | get${simpleClassName}List, |
| 19 | - import${simpleClassName}, | |
| 20 | - import${simpleClassName}Template, | |
| 21 | 19 | } from '#/api/${table.moduleName}/${table.businessName}'; |
| 22 | 20 | #else## 标准表接口 |
| 23 | 21 | import { |
| ... | ... | @@ -26,10 +24,11 @@ import { |
| 26 | 24 | delete${simpleClassName}List,#end |
| 27 | 25 | export${simpleClassName}, |
| 28 | 26 | get${simpleClassName}Page, |
| 29 | - import${simpleClassName}, | |
| 30 | - import${simpleClassName}Template, | |
| 31 | 27 | } from '#/api/${table.moduleName}/${table.businessName}'; |
| 32 | 28 | #end |
| 29 | +#if ($importEnable) | |
| 30 | +import ${simpleClassName}Import from './modules/import-form.vue'; | |
| 31 | +#end | |
| 33 | 32 | import { $t } from '#/locales'; |
| 34 | 33 | |
| 35 | 34 | import { useGridColumns, useGridFormSchema } from './data'; |
| ... | ... | @@ -54,8 +53,17 @@ const [FormModal, formModalApi] = useVbenModal({ |
| 54 | 53 | connectedComponent: Form, |
| 55 | 54 | destroyOnClose: true, |
| 56 | 55 | }); |
| 57 | -const importLoading = ref(false); | |
| 58 | -const importFileRef = ref<HTMLInputElement>(); | |
| 56 | +#if ($importEnable) | |
| 57 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 58 | + connectedComponent: ${simpleClassName}Import, | |
| 59 | + destroyOnClose: true, | |
| 60 | +}); | |
| 61 | + | |
| 62 | +/** 导入${table.classComment} */ | |
| 63 | +function handleImport() { | |
| 64 | + importFormModalApi.open(); | |
| 65 | +} | |
| 66 | +#end | |
| 59 | 67 | #if (${table.templateType} == 2)## 树表特有:控制表格展开收缩 |
| 60 | 68 | |
| 61 | 69 | /** 切换树形展开/收缩状态 */ |
| ... | ... | @@ -141,43 +149,6 @@ async function handleExport() { |
| 141 | 149 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); |
| 142 | 150 | } |
| 143 | 151 | |
| 144 | -/** 导入模板下载 */ | |
| 145 | -async function handleImportTemplateDownload() { | |
| 146 | - const data = await import${simpleClassName}Template(); | |
| 147 | - downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 148 | -} | |
| 149 | - | |
| 150 | -/** 导入按钮操作 */ | |
| 151 | -function handleImport() { | |
| 152 | - importFileRef.value?.click(); | |
| 153 | -} | |
| 154 | - | |
| 155 | -/** 导入文件变更 */ | |
| 156 | -async function handleImportFileChange(event: Event) { | |
| 157 | - const target = event.target as HTMLInputElement; | |
| 158 | - const file = target.files?.[0]; | |
| 159 | - if (!file) { | |
| 160 | - return; | |
| 161 | - } | |
| 162 | - importLoading.value = true; | |
| 163 | - try { | |
| 164 | - const formData = new FormData(); | |
| 165 | - formData.append('file', file); | |
| 166 | - const response: any = await import${simpleClassName}(formData); | |
| 167 | - const data = response?.data ?? response ?? {}; | |
| 168 | - let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 169 | - if (data.failureRows) { | |
| 170 | - Object.keys(data.failureRows).forEach((rowNo) => { | |
| 171 | - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 172 | - }); | |
| 173 | - } | |
| 174 | - message.info(text); | |
| 175 | - handleRefresh(); | |
| 176 | - } finally { | |
| 177 | - target.value = ''; | |
| 178 | - importLoading.value = false; | |
| 179 | - } | |
| 180 | -} | |
| 181 | 152 | |
| 182 | 153 | const [Grid, gridApi] = useVbenVxeGrid({ |
| 183 | 154 | formOptions: { |
| ... | ... | @@ -254,7 +225,9 @@ const [Grid, gridApi] = useVbenVxeGrid({ |
| 254 | 225 | <template> |
| 255 | 226 | <Page auto-content-height> |
| 256 | 227 | <FormModal @success="handleRefresh" /> |
| 257 | - <input ref="importFileRef" type="file" accept=".xls,.xlsx" class="hidden" @change="handleImportFileChange" /> | |
| 228 | +#if ($importEnable) | |
| 229 | + <ImportFormModal @success="handleRefresh" /> | |
| 230 | +#end | |
| 258 | 231 | #if ($table.templateType == 11) ## erp情况 |
| 259 | 232 | <div> |
| 260 | 233 | #end |
| ... | ... | @@ -292,19 +265,14 @@ const [Grid, gridApi] = useVbenVxeGrid({ |
| 292 | 265 | onClick: handleExpand, |
| 293 | 266 | }, |
| 294 | 267 | #end |
| 268 | +#if ($importEnable) | |
| 295 | 269 | { |
| 296 | 270 | label: '导入', |
| 297 | 271 | type: 'primary', |
| 298 | 272 | auth: ['${table.moduleName}:${simpleClassName_strikeCase}:import'], |
| 299 | - disabled: importLoading.value, | |
| 300 | 273 | onClick: handleImport, |
| 301 | 274 | }, |
| 302 | - { | |
| 303 | - label: '导入模板', | |
| 304 | - type: 'primary', | |
| 305 | - auth: ['${table.moduleName}:${simpleClassName_strikeCase}:import'], | |
| 306 | - onClick: handleImportTemplateDownload, | |
| 307 | - }, | |
| 275 | +#end | |
| 308 | 276 | { |
| 309 | 277 | label: $t('ui.actionTitle.export'), |
| 310 | 278 | type: 'primary', | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/api/api.ts.vm
| ... | ... | @@ -100,6 +100,7 @@ export function delete${simpleClassName}List(ids: number[]) { |
| 100 | 100 | export function export${simpleClassName}(params: any) { |
| 101 | 101 | return requestClient.download('${baseURL}/export-excel', { params }); |
| 102 | 102 | } |
| 103 | +#if ($importEnable) | |
| 103 | 104 | |
| 104 | 105 | /** 下载${table.classComment}导入模板 */ |
| 105 | 106 | export function import${simpleClassName}Template() { |
| ... | ... | @@ -110,6 +111,7 @@ export function import${simpleClassName}Template() { |
| 110 | 111 | export function import${simpleClassName}(data: FormData) { |
| 111 | 112 | return requestClient.post('${baseURL}/import', data); |
| 112 | 113 | } |
| 114 | +#end | |
| 113 | 115 | |
| 114 | 116 | ## 特殊:主子表专属逻辑 |
| 115 | 117 | #foreach ($subTable in $subTables) | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/import.vue.vm
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import { ref } from 'vue'; | |
| 3 | + | |
| 4 | +import { useVbenModal } from '@vben/common-ui'; | |
| 5 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 6 | + | |
| 7 | +import { ElButton, ElMessage, ElUpload } from 'element-plus'; | |
| 8 | + | |
| 9 | +import { import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 10 | + | |
| 11 | +defineOptions({ name: '${simpleClassName}Import' }); | |
| 12 | + | |
| 13 | +const emit = defineEmits(['success']); | |
| 14 | +const fileRef = ref<File | null>(null); | |
| 15 | + | |
| 16 | +const [Modal, modalApi] = useVbenModal({ | |
| 17 | + async onConfirm() { | |
| 18 | + if (!fileRef.value) { | |
| 19 | + ElMessage.error('请上传文件'); | |
| 20 | + return; | |
| 21 | + } | |
| 22 | + modalApi.lock(); | |
| 23 | + try { | |
| 24 | + const formData = new FormData(); | |
| 25 | + formData.append('file', fileRef.value); | |
| 26 | + const response: any = await import${simpleClassName}(formData); | |
| 27 | + const data = response?.data ?? response ?? {}; | |
| 28 | + let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 29 | + if (data.failureRows) { | |
| 30 | + Object.keys(data.failureRows).forEach((rowNo) => { | |
| 31 | + text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 32 | + }); | |
| 33 | + } | |
| 34 | + ElMessage.info(text); | |
| 35 | + await modalApi.close(); | |
| 36 | + emit('success'); | |
| 37 | + } finally { | |
| 38 | + modalApi.unlock(); | |
| 39 | + } | |
| 40 | + }, | |
| 41 | +}); | |
| 42 | + | |
| 43 | +/** 文件改变 */ | |
| 44 | +function handleChange(file: any) { | |
| 45 | + if (file.raw) { | |
| 46 | + fileRef.value = file.raw; | |
| 47 | + } | |
| 48 | +} | |
| 49 | + | |
| 50 | +/** 下载导入模板 */ | |
| 51 | +async function handleDownload() { | |
| 52 | + const data = await import${simpleClassName}Template(); | |
| 53 | + downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 54 | +} | |
| 55 | +</script> | |
| 56 | + | |
| 57 | +<template> | |
| 58 | + <Modal title="导入${table.classComment}" class="w-1/3"> | |
| 59 | + <div class="mx-4"> | |
| 60 | + <ElUpload | |
| 61 | + :limit="1" | |
| 62 | + accept=".xls,.xlsx" | |
| 63 | + :on-change="handleChange" | |
| 64 | + :auto-upload="false" | |
| 65 | + > | |
| 66 | + <ElButton type="primary"> 选择 Excel 文件 </ElButton> | |
| 67 | + </ElUpload> | |
| 68 | + </div> | |
| 69 | + <template #prepend-footer> | |
| 70 | + <div class="flex flex-auto items-center"> | |
| 71 | + <ElButton @click="handleDownload"> 下载导入模板 </ElButton> | |
| 72 | + </div> | |
| 73 | + </template> | |
| 74 | + </Modal> | |
| 75 | +</template> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/index.vue.vm
| ... | ... | @@ -26,10 +26,13 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; |
| 26 | 26 | import { $t } from '#/locales'; |
| 27 | 27 | #if (${table.templateType} == 2)## 树表接口 |
| 28 | 28 | import { handleTree,isEmpty } from '@vben/utils' |
| 29 | -import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName}, import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | |
| 29 | +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | |
| 30 | 30 | #else## 标准表接口 |
| 31 | 31 | import { isEmpty } from '@vben/utils'; |
| 32 | -import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName}, import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | |
| 32 | +import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | |
| 33 | +#end | |
| 34 | +#if ($importEnable) | |
| 35 | +import ${simpleClassName}Import from './modules/import-form.vue'; | |
| 33 | 36 | #end |
| 34 | 37 | |
| 35 | 38 | #if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况 |
| ... | ... | @@ -73,8 +76,6 @@ const queryParams = reactive({ |
| 73 | 76 | }) |
| 74 | 77 | const queryFormRef = ref() // 搜索的表单 |
| 75 | 78 | const exportLoading = ref(false) // 导出的加载中 |
| 76 | -const importLoading = ref(false) // 导入的加载中 | |
| 77 | -const importFileRef = ref<HTMLInputElement>() | |
| 78 | 79 | |
| 79 | 80 | /** 查询列表 */ |
| 80 | 81 | const getList = async () => { |
| ... | ... | @@ -121,6 +122,17 @@ const [FormModal, formModalApi] = useVbenModal({ |
| 121 | 122 | connectedComponent: ${simpleClassName}Form, |
| 122 | 123 | destroyOnClose: true, |
| 123 | 124 | }); |
| 125 | +#if ($importEnable) | |
| 126 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 127 | + connectedComponent: ${simpleClassName}Import, | |
| 128 | + destroyOnClose: true, | |
| 129 | +}); | |
| 130 | + | |
| 131 | +/** 导入${table.classComment} */ | |
| 132 | +function handleImport() { | |
| 133 | + importFormModalApi.open(); | |
| 134 | +} | |
| 135 | +#end | |
| 124 | 136 | |
| 125 | 137 | /** 创建${table.classComment} */ |
| 126 | 138 | function handleCreate() { |
| ... | ... | @@ -190,43 +202,6 @@ try { |
| 190 | 202 | } |
| 191 | 203 | } |
| 192 | 204 | |
| 193 | -/** 导入模板下载 */ | |
| 194 | -async function handleImportTemplateDownload() { | |
| 195 | - const data = await import${simpleClassName}Template(); | |
| 196 | - downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 197 | -} | |
| 198 | - | |
| 199 | -/** 导入按钮操作 */ | |
| 200 | -function handleImport() { | |
| 201 | - importFileRef.value?.click(); | |
| 202 | -} | |
| 203 | - | |
| 204 | -/** 导入文件变更 */ | |
| 205 | -async function handleImportFileChange(event: Event) { | |
| 206 | - const target = event.target as HTMLInputElement; | |
| 207 | - const file = target.files?.[0]; | |
| 208 | - if (!file) { | |
| 209 | - return; | |
| 210 | - } | |
| 211 | - importLoading.value = true; | |
| 212 | - try { | |
| 213 | - const formData = new FormData(); | |
| 214 | - formData.append('file', file); | |
| 215 | - const response: any = await import${simpleClassName}(formData); | |
| 216 | - const data = response?.data ?? response ?? {}; | |
| 217 | - let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 218 | - if (data.failureRows) { | |
| 219 | - Object.keys(data.failureRows).forEach((rowNo) => { | |
| 220 | - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 221 | - }); | |
| 222 | - } | |
| 223 | - ElMessage.info(text); | |
| 224 | - await getList(); | |
| 225 | - } finally { | |
| 226 | - target.value = ''; | |
| 227 | - importLoading.value = false; | |
| 228 | - } | |
| 229 | -} | |
| 230 | 205 | |
| 231 | 206 | #if (${table.templateType} == 2) |
| 232 | 207 | /** 切换树形展开/收缩状态 */ |
| ... | ... | @@ -247,7 +222,9 @@ onMounted(() => { |
| 247 | 222 | <template> |
| 248 | 223 | <Page auto-content-height> |
| 249 | 224 | <FormModal @success="getList" /> |
| 250 | - <input ref="importFileRef" type="file" accept=".xls,.xlsx" class="hidden" @change="handleImportFileChange" /> | |
| 225 | +#if ($importEnable) | |
| 226 | + <ImportFormModal @success="getList" /> | |
| 227 | +#end | |
| 251 | 228 | |
| 252 | 229 | <ContentWrap v-if="!hiddenSearchBar"> |
| 253 | 230 | <!-- 搜索工作栏 --> |
| ... | ... | @@ -356,23 +333,16 @@ onMounted(() => { |
| 356 | 333 | > |
| 357 | 334 | {{ $t('ui.actionTitle.create', ['${table.classComment}']) }} |
| 358 | 335 | </el-button> |
| 336 | +#if ($importEnable) | |
| 359 | 337 | <el-button |
| 360 | 338 | class="ml-2" |
| 361 | 339 | type="primary" |
| 362 | - :loading="importLoading" | |
| 363 | 340 | @click="handleImport" |
| 364 | 341 | v-access:code="['${permissionPrefix}:import']" |
| 365 | 342 | > |
| 366 | 343 | 导入 |
| 367 | 344 | </el-button> |
| 368 | - <el-button | |
| 369 | - class="ml-2" | |
| 370 | - type="primary" | |
| 371 | - @click="handleImportTemplateDownload" | |
| 372 | - v-access:code="['${permissionPrefix}:import']" | |
| 373 | - > | |
| 374 | - 导入模板 | |
| 375 | - </el-button> | |
| 345 | +#end | |
| 376 | 346 | <el-button |
| 377 | 347 | :icon="h(Download)" |
| 378 | 348 | type="primary" | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/api/api.ts.vm
| ... | ... | @@ -113,6 +113,7 @@ export function delete${simpleClassName}List(ids: number[]) { |
| 113 | 113 | export function export${simpleClassName}(params: any) { |
| 114 | 114 | return requestClient.download('${baseURL}/export-excel', { params }); |
| 115 | 115 | } |
| 116 | +#if ($importEnable) | |
| 116 | 117 | |
| 117 | 118 | /** 下载${table.classComment}导入模板 */ |
| 118 | 119 | export function import${simpleClassName}Template() { |
| ... | ... | @@ -120,9 +121,10 @@ export function import${simpleClassName}Template() { |
| 120 | 121 | } |
| 121 | 122 | |
| 122 | 123 | /** 导入${table.classComment} */ |
| 123 | -export function import${simpleClassName}(data: FormData) { | |
| 124 | - return requestClient.post('${baseURL}/import', data); | |
| 124 | +export function import${simpleClassName}(file: File) { | |
| 125 | + return requestClient.upload('${baseURL}/import', { file }); | |
| 125 | 126 | } |
| 127 | +#end | |
| 126 | 128 | |
| 127 | 129 | ## 特殊:主子表专属逻辑 |
| 128 | 130 | #foreach ($subTable in $subTables) | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm
| ... | ... | @@ -137,6 +137,21 @@ export function useFormSchema(): VbenFormSchema[] { |
| 137 | 137 | ]; |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | +#if ($importEnable) | |
| 141 | +/** 导入的表单 */ | |
| 142 | +export function useImportFormSchema(): VbenFormSchema[] { | |
| 143 | + return [ | |
| 144 | + { | |
| 145 | + fieldName: 'file', | |
| 146 | + label: '${table.classComment}数据', | |
| 147 | + component: 'Upload', | |
| 148 | + rules: 'required', | |
| 149 | + help: '仅允许导入 xls、xlsx 格式文件', | |
| 150 | + }, | |
| 151 | + ]; | |
| 152 | +} | |
| 153 | + | |
| 154 | +#end | |
| 140 | 155 | /** 列表的搜索表单 */ |
| 141 | 156 | export function useGridFormSchema(): VbenFormSchema[] { |
| 142 | 157 | return [ | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/import.vue.vm
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import { useVbenModal } from '@vben/common-ui'; | |
| 3 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 4 | + | |
| 5 | +import { ElButton, ElMessage, ElUpload } from 'element-plus'; | |
| 6 | + | |
| 7 | +import { useVbenForm } from '#/adapter/form'; | |
| 8 | +import { import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; | |
| 9 | +import { $t } from '#/locales'; | |
| 10 | + | |
| 11 | +import { useImportFormSchema } from '../data'; | |
| 12 | + | |
| 13 | +const emit = defineEmits(['success']); | |
| 14 | + | |
| 15 | +const [Form, formApi] = useVbenForm({ | |
| 16 | + commonConfig: { | |
| 17 | + formItemClass: 'col-span-2', | |
| 18 | + labelWidth: 120, | |
| 19 | + }, | |
| 20 | + layout: 'horizontal', | |
| 21 | + schema: useImportFormSchema(), | |
| 22 | + showDefaultActions: false, | |
| 23 | +}); | |
| 24 | + | |
| 25 | +const [Modal, modalApi] = useVbenModal({ | |
| 26 | + async onConfirm() { | |
| 27 | + const { valid } = await formApi.validate(); | |
| 28 | + if (!valid) { | |
| 29 | + return; | |
| 30 | + } | |
| 31 | + modalApi.lock(); | |
| 32 | + // 提交表单 | |
| 33 | + const data = await formApi.getValues(); | |
| 34 | + try { | |
| 35 | + await import${simpleClassName}(data.file); | |
| 36 | + // 关闭并提示 | |
| 37 | + await modalApi.close(); | |
| 38 | + emit('success'); | |
| 39 | + ElMessage.success($t('ui.actionMessage.operationSuccess')); | |
| 40 | + } finally { | |
| 41 | + modalApi.unlock(); | |
| 42 | + } | |
| 43 | + }, | |
| 44 | +}); | |
| 45 | + | |
| 46 | +/** 文件改变时 */ | |
| 47 | +function handleChange(file: any) { | |
| 48 | + if (file.raw) { | |
| 49 | + formApi.setFieldValue('file', file.raw); | |
| 50 | + } | |
| 51 | +} | |
| 52 | + | |
| 53 | +/** 下载模板 */ | |
| 54 | +async function handleDownload() { | |
| 55 | + const data = await import${simpleClassName}Template(); | |
| 56 | + downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 57 | +} | |
| 58 | +</script> | |
| 59 | + | |
| 60 | +<template> | |
| 61 | + <Modal title="导入${table.classComment}" class="w-1/3"> | |
| 62 | + <Form class="mx-4"> | |
| 63 | + <template #file> | |
| 64 | + <div class="w-full"> | |
| 65 | + <ElUpload | |
| 66 | + :limit="1" | |
| 67 | + accept=".xls,.xlsx" | |
| 68 | + :on-change="handleChange" | |
| 69 | + :auto-upload="false" | |
| 70 | + > | |
| 71 | + <ElButton type="primary"> 选择 Excel 文件 </ElButton> | |
| 72 | + </ElUpload> | |
| 73 | + </div> | |
| 74 | + </template> | |
| 75 | + </Form> | |
| 76 | + <template #prepend-footer> | |
| 77 | + <div class="flex flex-auto items-center"> | |
| 78 | + <ElButton @click="handleDownload"> 下载导入模板 </ElButton> | |
| 79 | + </div> | |
| 80 | + </template> | |
| 81 | + </Modal> | |
| 82 | +</template> | ... | ... |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm
| ... | ... | @@ -16,8 +16,6 @@ import { |
| 16 | 16 | delete${simpleClassName}, |
| 17 | 17 | export${simpleClassName}, |
| 18 | 18 | get${simpleClassName}List, |
| 19 | - import${simpleClassName}, | |
| 20 | - import${simpleClassName}Template, | |
| 21 | 19 | } from '#/api/${table.moduleName}/${table.businessName}'; |
| 22 | 20 | #else## 标准表接口 |
| 23 | 21 | import { |
| ... | ... | @@ -26,10 +24,11 @@ import { |
| 26 | 24 | delete${simpleClassName}List,#end |
| 27 | 25 | export${simpleClassName}, |
| 28 | 26 | get${simpleClassName}Page, |
| 29 | - import${simpleClassName}, | |
| 30 | - import${simpleClassName}Template, | |
| 31 | 27 | } from '#/api/${table.moduleName}/${table.businessName}'; |
| 32 | 28 | #end |
| 29 | +#if ($importEnable) | |
| 30 | +import ${simpleClassName}Import from './modules/import-form.vue'; | |
| 31 | +#end | |
| 33 | 32 | import { $t } from '#/locales'; |
| 34 | 33 | |
| 35 | 34 | import { useGridColumns, useGridFormSchema } from './data'; |
| ... | ... | @@ -54,8 +53,17 @@ const [FormModal, formModalApi] = useVbenModal({ |
| 54 | 53 | connectedComponent: Form, |
| 55 | 54 | destroyOnClose: true, |
| 56 | 55 | }); |
| 57 | -const importLoading = ref(false); | |
| 58 | -const importFileRef = ref<HTMLInputElement>(); | |
| 56 | +#if ($importEnable) | |
| 57 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 58 | + connectedComponent: ${simpleClassName}Import, | |
| 59 | + destroyOnClose: true, | |
| 60 | +}); | |
| 61 | + | |
| 62 | +/** 导入${table.classComment} */ | |
| 63 | +function handleImport() { | |
| 64 | + importFormModalApi.open(); | |
| 65 | +} | |
| 66 | +#end | |
| 59 | 67 | #if (${table.templateType} == 2)## 树表特有:控制表格展开收缩 |
| 60 | 68 | |
| 61 | 69 | /** 切换树形展开/收缩状态 */ |
| ... | ... | @@ -139,43 +147,6 @@ async function handleExport() { |
| 139 | 147 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); |
| 140 | 148 | } |
| 141 | 149 | |
| 142 | -/** 导入模板下载 */ | |
| 143 | -async function handleImportTemplateDownload() { | |
| 144 | - const data = await import${simpleClassName}Template(); | |
| 145 | - downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); | |
| 146 | -} | |
| 147 | - | |
| 148 | -/** 导入按钮操作 */ | |
| 149 | -function handleImport() { | |
| 150 | - importFileRef.value?.click(); | |
| 151 | -} | |
| 152 | - | |
| 153 | -/** 导入文件变更 */ | |
| 154 | -async function handleImportFileChange(event: Event) { | |
| 155 | - const target = event.target as HTMLInputElement; | |
| 156 | - const file = target.files?.[0]; | |
| 157 | - if (!file) { | |
| 158 | - return; | |
| 159 | - } | |
| 160 | - importLoading.value = true; | |
| 161 | - try { | |
| 162 | - const formData = new FormData(); | |
| 163 | - formData.append('file', file); | |
| 164 | - const response: any = await import${simpleClassName}(formData); | |
| 165 | - const data = response?.data ?? response ?? {}; | |
| 166 | - let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 167 | - if (data.failureRows) { | |
| 168 | - Object.keys(data.failureRows).forEach((rowNo) => { | |
| 169 | - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 170 | - }); | |
| 171 | - } | |
| 172 | - ElMessage.info(text); | |
| 173 | - handleRefresh(); | |
| 174 | - } finally { | |
| 175 | - target.value = ''; | |
| 176 | - importLoading.value = false; | |
| 177 | - } | |
| 178 | -} | |
| 179 | 150 | |
| 180 | 151 | const [Grid, gridApi] = useVbenVxeGrid({ |
| 181 | 152 | formOptions: { |
| ... | ... | @@ -252,7 +223,9 @@ const [Grid, gridApi] = useVbenVxeGrid({ |
| 252 | 223 | <template> |
| 253 | 224 | <Page auto-content-height> |
| 254 | 225 | <FormModal @success="handleRefresh" /> |
| 255 | - <input ref="importFileRef" type="file" accept=".xls,.xlsx" class="hidden" @change="handleImportFileChange" /> | |
| 226 | +#if ($importEnable) | |
| 227 | + <ImportFormModal @success="handleRefresh" /> | |
| 228 | +#end | |
| 256 | 229 | #if ($table.templateType == 11) ## erp情况 |
| 257 | 230 | <div> |
| 258 | 231 | #end |
| ... | ... | @@ -290,19 +263,14 @@ const [Grid, gridApi] = useVbenVxeGrid({ |
| 290 | 263 | onClick: handleExpand, |
| 291 | 264 | }, |
| 292 | 265 | #end |
| 266 | +#if ($importEnable) | |
| 293 | 267 | { |
| 294 | 268 | label: '导入', |
| 295 | 269 | type: 'primary', |
| 296 | 270 | auth: ['${table.moduleName}:${simpleClassName_strikeCase}:import'], |
| 297 | - disabled: importLoading.value, | |
| 298 | 271 | onClick: handleImport, |
| 299 | 272 | }, |
| 300 | - { | |
| 301 | - label: '导入模板', | |
| 302 | - type: 'primary', | |
| 303 | - auth: ['${table.moduleName}:${simpleClassName_strikeCase}:import'], | |
| 304 | - onClick: handleImportTemplateDownload, | |
| 305 | - }, | |
| 273 | +#end | |
| 306 | 274 | { |
| 307 | 275 | label: $t('ui.actionTitle.export'), |
| 308 | 276 | type: 'primary', | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java
| ... | ... | @@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 10 | 10 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| 11 | 11 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; |
| 12 | 12 | import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; |
| 13 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenVOTypeEnum; | |
| 13 | 14 | import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; |
| 14 | 15 | import org.junit.jupiter.api.BeforeEach; |
| 15 | 16 | import org.mockito.InjectMocks; |
| ... | ... | @@ -19,8 +20,10 @@ import java.io.ByteArrayInputStream; |
| 19 | 20 | import java.io.ByteArrayOutputStream; |
| 20 | 21 | import java.util.ArrayList; |
| 21 | 22 | import java.util.HashMap; |
| 23 | +import java.util.LinkedHashSet; | |
| 22 | 24 | import java.util.List; |
| 23 | 25 | import java.util.Map; |
| 26 | +import java.util.Set; | |
| 24 | 27 | |
| 25 | 28 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 26 | 29 | |
| ... | ... | @@ -41,16 +44,18 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest { |
| 41 | 44 | |
| 42 | 45 | @Spy |
| 43 | 46 | protected CodegenProperties codegenProperties = new CodegenProperties() |
| 44 | - .setBasePackage("cn.iocoder.yudao"); | |
| 47 | + .setBasePackage("cn.iocoder.yudao") | |
| 48 | + .setVoType(CodegenVOTypeEnum.VO.getType()) | |
| 49 | + .setDeleteBatchEnable(true) | |
| 50 | + .setUnitTestEnable(true) | |
| 51 | + .setImportEnable(false); | |
| 45 | 52 | |
| 46 | 53 | @BeforeEach |
| 47 | 54 | public void setUp() { |
| 48 | 55 | codegenEngine.setJakartaEnable(true); // 强制使用 jakarta,保证单测可以基于 jakarta 断言 |
| 49 | 56 | codegenEngine.initGlobalBindingMap(); |
| 50 | - // 单测强制使用 | |
| 51 | - // 获取测试文件 resources 路径 | |
| 57 | + // 获取测试文件 resources 路径,writeResult 调试用 | |
| 52 | 58 | String absolutePath = FileUtil.getAbsolutePath("application-unit-test.yaml"); |
| 53 | - // 系统不一样生成的文件也有差异,那就各自生成各自的 | |
| 54 | 59 | resourcesPath = absolutePath.split("/target")[0] + "/src/test/resources/codegen/"; |
| 55 | 60 | } |
| 56 | 61 | |
| ... | ... | @@ -82,17 +87,32 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest { |
| 82 | 87 | return list; |
| 83 | 88 | } |
| 84 | 89 | |
| 90 | + /** | |
| 91 | + * 重新生成断言数据的开关,命令行加 {@code -Dcodegen.regenerate=true} 启用 | |
| 92 | + */ | |
| 93 | + private static final boolean REGENERATE = Boolean.parseBoolean(System.getProperty("codegen.regenerate", "false")); | |
| 94 | + | |
| 85 | 95 | @SuppressWarnings("rawtypes") |
| 86 | - protected static void assertResult(Map<String, String> result, String path) { | |
| 96 | + protected void assertResult(Map<String, String> result, String path) { | |
| 97 | + if (REGENERATE) { | |
| 98 | + writeResult(result, resourcesPath + path); | |
| 99 | + return; | |
| 100 | + } | |
| 87 | 101 | String assertContent = ResourceUtil.readUtf8Str("codegen/" + path + "/assert.json"); |
| 88 | 102 | List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class); |
| 89 | - assertEquals(asserts.size(), result.size()); | |
| 90 | - // 校验每个文件 | |
| 103 | + Set<String> expectedFiles = asserts.stream() | |
| 104 | + .map(m -> (String) m.get("filePath")) | |
| 105 | + .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new)); | |
| 106 | + assertEquals(expectedFiles, result.keySet(), "生成文件集合不匹配"); | |
| 107 | + // 校验每个文件;归一化 \r\n 为 \n,让断言不依赖文件落盘的换行风格 | |
| 91 | 108 | asserts.forEach(assertMap -> { |
| 92 | 109 | String contentPath = (String) assertMap.get("contentPath"); |
| 93 | 110 | String filePath = (String) assertMap.get("filePath"); |
| 94 | - String content = ResourceUtil.readUtf8Str("codegen/" + path + "/" + contentPath); | |
| 95 | - assertEquals(content, result.get(filePath), filePath + ":不匹配"); | |
| 111 | + String expected = ResourceUtil.readUtf8Str("codegen/" + path + "/" + contentPath) | |
| 112 | + .replace("\r\n", "\n"); | |
| 113 | + String actual = result.get(filePath); | |
| 114 | + assertEquals(expected, actual == null ? null : actual.replace("\r\n", "\n"), | |
| 115 | + filePath + ":不匹配"); | |
| 96 | 116 | }); |
| 97 | 117 | } |
| 98 | 118 | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVben5AntdGeneralTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.codegen.inner; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; | |
| 4 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; | |
| 5 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; | |
| 7 | +import com.baomidou.mybatisplus.annotation.DbType; | |
| 8 | +import org.junit.jupiter.api.Test; | |
| 9 | + | |
| 10 | +import java.util.Arrays; | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.Map; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * {@link CodegenEngine} 的 Vue3 + Vben5 + AntD + General 单元测试 | |
| 16 | + * | |
| 17 | + * @author 芋道源码 | |
| 18 | + */ | |
| 19 | +public class CodegenEngineVben5AntdGeneralTest extends CodegenEngineAbstractTest { | |
| 20 | + | |
| 21 | + private static final Integer FRONT_TYPE = CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(); | |
| 22 | + | |
| 23 | + @Test | |
| 24 | + public void testExecute_one() { | |
| 25 | + // 准备参数 | |
| 26 | + CodegenTableDO table = getTable("student") | |
| 27 | + .setFrontType(FRONT_TYPE) | |
| 28 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 29 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 30 | + | |
| 31 | + // 调用 | |
| 32 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 33 | + // 断言 | |
| 34 | + assertResult(result, "/vben5_antd_general_one"); | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Test | |
| 38 | + public void testExecute_one_importEnable() { | |
| 39 | + // 开启 import 开关 | |
| 40 | + codegenProperties.setImportEnable(true); | |
| 41 | + codegenEngine.initGlobalBindingMap(); | |
| 42 | + // 准备参数 | |
| 43 | + CodegenTableDO table = getTable("student") | |
| 44 | + .setFrontType(FRONT_TYPE) | |
| 45 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 46 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 47 | + | |
| 48 | + // 调用 | |
| 49 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 50 | + // 断言 | |
| 51 | + assertResult(result, "/vben5_antd_general_one_importEnable"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Test | |
| 55 | + public void testExecute_tree() { | |
| 56 | + // 准备参数 | |
| 57 | + CodegenTableDO table = getTable("category") | |
| 58 | + .setFrontType(FRONT_TYPE) | |
| 59 | + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); | |
| 60 | + List<CodegenColumnDO> columns = getColumnList("category"); | |
| 61 | + | |
| 62 | + // 调用 | |
| 63 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 64 | + // 断言 | |
| 65 | + assertResult(result, "/vben5_antd_general_tree"); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Test | |
| 69 | + public void testExecute_master_normal() { | |
| 70 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "/vben5_antd_general_master_normal"); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Test | |
| 74 | + public void testExecute_master_erp() { | |
| 75 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_ERP, "/vben5_antd_general_master_erp"); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Test | |
| 79 | + public void testExecute_master_inner() { | |
| 80 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_INNER, "/vben5_antd_general_master_inner"); | |
| 81 | + } | |
| 82 | + | |
| 83 | + private void testExecute_master(CodegenTemplateTypeEnum templateType, String path) { | |
| 84 | + // 准备参数 | |
| 85 | + CodegenTableDO table = getTable("student") | |
| 86 | + .setFrontType(FRONT_TYPE) | |
| 87 | + .setTemplateType(templateType.getType()); | |
| 88 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 89 | + // 准备参数(子表) | |
| 90 | + CodegenTableDO contactTable = getTable("contact") | |
| 91 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 92 | + .setFrontType(FRONT_TYPE) | |
| 93 | + .setSubJoinColumnId(100L).setSubJoinMany(true); | |
| 94 | + List<CodegenColumnDO> contactColumns = getColumnList("contact"); | |
| 95 | + // 准备参数(班主任) | |
| 96 | + CodegenTableDO teacherTable = getTable("teacher") | |
| 97 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 98 | + .setFrontType(FRONT_TYPE) | |
| 99 | + .setSubJoinColumnId(200L).setSubJoinMany(false); | |
| 100 | + List<CodegenColumnDO> teacherColumns = getColumnList("teacher"); | |
| 101 | + | |
| 102 | + // 调用 | |
| 103 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, | |
| 104 | + Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns)); | |
| 105 | + // 断言 | |
| 106 | + assertResult(result, path); | |
| 107 | + } | |
| 108 | + | |
| 109 | +} | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVben5AntdSchemaTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.codegen.inner; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; | |
| 4 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; | |
| 5 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; | |
| 7 | +import com.baomidou.mybatisplus.annotation.DbType; | |
| 8 | +import org.junit.jupiter.api.Test; | |
| 9 | + | |
| 10 | +import java.util.Arrays; | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.Map; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * {@link CodegenEngine} 的 Vue3 + Vben5 + AntD + Schema 单元测试 | |
| 16 | + * | |
| 17 | + * @author 芋道源码 | |
| 18 | + */ | |
| 19 | +public class CodegenEngineVben5AntdSchemaTest extends CodegenEngineAbstractTest { | |
| 20 | + | |
| 21 | + private static final Integer FRONT_TYPE = CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(); | |
| 22 | + | |
| 23 | + @Test | |
| 24 | + public void testExecute_one() { | |
| 25 | + // 准备参数 | |
| 26 | + CodegenTableDO table = getTable("student") | |
| 27 | + .setFrontType(FRONT_TYPE) | |
| 28 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 29 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 30 | + | |
| 31 | + // 调用 | |
| 32 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 33 | + // 断言 | |
| 34 | + assertResult(result, "/vben5_antd_schema_one"); | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Test | |
| 38 | + public void testExecute_one_importEnable() { | |
| 39 | + // 开启 import 开关 | |
| 40 | + codegenProperties.setImportEnable(true); | |
| 41 | + codegenEngine.initGlobalBindingMap(); | |
| 42 | + // 准备参数 | |
| 43 | + CodegenTableDO table = getTable("student") | |
| 44 | + .setFrontType(FRONT_TYPE) | |
| 45 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 46 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 47 | + | |
| 48 | + // 调用 | |
| 49 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 50 | + // 断言 | |
| 51 | + assertResult(result, "/vben5_antd_schema_one_importEnable"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Test | |
| 55 | + public void testExecute_tree() { | |
| 56 | + // 准备参数 | |
| 57 | + CodegenTableDO table = getTable("category") | |
| 58 | + .setFrontType(FRONT_TYPE) | |
| 59 | + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); | |
| 60 | + List<CodegenColumnDO> columns = getColumnList("category"); | |
| 61 | + | |
| 62 | + // 调用 | |
| 63 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 64 | + // 断言 | |
| 65 | + assertResult(result, "/vben5_antd_schema_tree"); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Test | |
| 69 | + public void testExecute_master_normal() { | |
| 70 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "/vben5_antd_schema_master_normal"); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Test | |
| 74 | + public void testExecute_master_erp() { | |
| 75 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_ERP, "/vben5_antd_schema_master_erp"); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Test | |
| 79 | + public void testExecute_master_inner() { | |
| 80 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_INNER, "/vben5_antd_schema_master_inner"); | |
| 81 | + } | |
| 82 | + | |
| 83 | + private void testExecute_master(CodegenTemplateTypeEnum templateType, String path) { | |
| 84 | + // 准备参数 | |
| 85 | + CodegenTableDO table = getTable("student") | |
| 86 | + .setFrontType(FRONT_TYPE) | |
| 87 | + .setTemplateType(templateType.getType()); | |
| 88 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 89 | + // 准备参数(子表) | |
| 90 | + CodegenTableDO contactTable = getTable("contact") | |
| 91 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 92 | + .setFrontType(FRONT_TYPE) | |
| 93 | + .setSubJoinColumnId(100L).setSubJoinMany(true); | |
| 94 | + List<CodegenColumnDO> contactColumns = getColumnList("contact"); | |
| 95 | + // 准备参数(班主任) | |
| 96 | + CodegenTableDO teacherTable = getTable("teacher") | |
| 97 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 98 | + .setFrontType(FRONT_TYPE) | |
| 99 | + .setSubJoinColumnId(200L).setSubJoinMany(false); | |
| 100 | + List<CodegenColumnDO> teacherColumns = getColumnList("teacher"); | |
| 101 | + | |
| 102 | + // 调用 | |
| 103 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, | |
| 104 | + Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns)); | |
| 105 | + // 断言 | |
| 106 | + assertResult(result, path); | |
| 107 | + } | |
| 108 | + | |
| 109 | +} | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVben5EleGeneralTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.codegen.inner; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; | |
| 4 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; | |
| 5 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; | |
| 7 | +import com.baomidou.mybatisplus.annotation.DbType; | |
| 8 | +import org.junit.jupiter.api.Test; | |
| 9 | + | |
| 10 | +import java.util.Arrays; | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.Map; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * {@link CodegenEngine} 的 Vue3 + Vben5 + Element Plus + General 单元测试 | |
| 16 | + * | |
| 17 | + * @author 芋道源码 | |
| 18 | + */ | |
| 19 | +public class CodegenEngineVben5EleGeneralTest extends CodegenEngineAbstractTest { | |
| 20 | + | |
| 21 | + private static final Integer FRONT_TYPE = CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(); | |
| 22 | + | |
| 23 | + @Test | |
| 24 | + public void testExecute_one() { | |
| 25 | + // 准备参数 | |
| 26 | + CodegenTableDO table = getTable("student") | |
| 27 | + .setFrontType(FRONT_TYPE) | |
| 28 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 29 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 30 | + | |
| 31 | + // 调用 | |
| 32 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 33 | + // 断言 | |
| 34 | + assertResult(result, "/vben5_ele_general_one"); | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Test | |
| 38 | + public void testExecute_one_importEnable() { | |
| 39 | + // 开启 import 开关 | |
| 40 | + codegenProperties.setImportEnable(true); | |
| 41 | + codegenEngine.initGlobalBindingMap(); | |
| 42 | + // 准备参数 | |
| 43 | + CodegenTableDO table = getTable("student") | |
| 44 | + .setFrontType(FRONT_TYPE) | |
| 45 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 46 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 47 | + | |
| 48 | + // 调用 | |
| 49 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 50 | + // 断言 | |
| 51 | + assertResult(result, "/vben5_ele_general_one_importEnable"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Test | |
| 55 | + public void testExecute_tree() { | |
| 56 | + // 准备参数 | |
| 57 | + CodegenTableDO table = getTable("category") | |
| 58 | + .setFrontType(FRONT_TYPE) | |
| 59 | + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); | |
| 60 | + List<CodegenColumnDO> columns = getColumnList("category"); | |
| 61 | + | |
| 62 | + // 调用 | |
| 63 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 64 | + // 断言 | |
| 65 | + assertResult(result, "/vben5_ele_general_tree"); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Test | |
| 69 | + public void testExecute_master_normal() { | |
| 70 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "/vben5_ele_general_master_normal"); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Test | |
| 74 | + public void testExecute_master_erp() { | |
| 75 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_ERP, "/vben5_ele_general_master_erp"); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Test | |
| 79 | + public void testExecute_master_inner() { | |
| 80 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_INNER, "/vben5_ele_general_master_inner"); | |
| 81 | + } | |
| 82 | + | |
| 83 | + private void testExecute_master(CodegenTemplateTypeEnum templateType, String path) { | |
| 84 | + // 准备参数 | |
| 85 | + CodegenTableDO table = getTable("student") | |
| 86 | + .setFrontType(FRONT_TYPE) | |
| 87 | + .setTemplateType(templateType.getType()); | |
| 88 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 89 | + // 准备参数(子表) | |
| 90 | + CodegenTableDO contactTable = getTable("contact") | |
| 91 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 92 | + .setFrontType(FRONT_TYPE) | |
| 93 | + .setSubJoinColumnId(100L).setSubJoinMany(true); | |
| 94 | + List<CodegenColumnDO> contactColumns = getColumnList("contact"); | |
| 95 | + // 准备参数(班主任) | |
| 96 | + CodegenTableDO teacherTable = getTable("teacher") | |
| 97 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 98 | + .setFrontType(FRONT_TYPE) | |
| 99 | + .setSubJoinColumnId(200L).setSubJoinMany(false); | |
| 100 | + List<CodegenColumnDO> teacherColumns = getColumnList("teacher"); | |
| 101 | + | |
| 102 | + // 调用 | |
| 103 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, | |
| 104 | + Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns)); | |
| 105 | + // 断言 | |
| 106 | + assertResult(result, path); | |
| 107 | + } | |
| 108 | + | |
| 109 | +} | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVben5EleSchemaTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.codegen.inner; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; | |
| 4 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; | |
| 5 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; | |
| 7 | +import com.baomidou.mybatisplus.annotation.DbType; | |
| 8 | +import org.junit.jupiter.api.Test; | |
| 9 | + | |
| 10 | +import java.util.Arrays; | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.Map; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * {@link CodegenEngine} 的 Vue3 + Vben5 + Element Plus + Schema 单元测试 | |
| 16 | + * | |
| 17 | + * @author 芋道源码 | |
| 18 | + */ | |
| 19 | +public class CodegenEngineVben5EleSchemaTest extends CodegenEngineAbstractTest { | |
| 20 | + | |
| 21 | + private static final Integer FRONT_TYPE = CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(); | |
| 22 | + | |
| 23 | + @Test | |
| 24 | + public void testExecute_one() { | |
| 25 | + // 准备参数 | |
| 26 | + CodegenTableDO table = getTable("student") | |
| 27 | + .setFrontType(FRONT_TYPE) | |
| 28 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 29 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 30 | + | |
| 31 | + // 调用 | |
| 32 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 33 | + // 断言 | |
| 34 | + assertResult(result, "/vben5_ele_schema_one"); | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Test | |
| 38 | + public void testExecute_one_importEnable() { | |
| 39 | + // 开启 import 开关 | |
| 40 | + codegenProperties.setImportEnable(true); | |
| 41 | + codegenEngine.initGlobalBindingMap(); | |
| 42 | + // 准备参数 | |
| 43 | + CodegenTableDO table = getTable("student") | |
| 44 | + .setFrontType(FRONT_TYPE) | |
| 45 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 46 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 47 | + | |
| 48 | + // 调用 | |
| 49 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 50 | + // 断言 | |
| 51 | + assertResult(result, "/vben5_ele_schema_one_importEnable"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Test | |
| 55 | + public void testExecute_tree() { | |
| 56 | + // 准备参数 | |
| 57 | + CodegenTableDO table = getTable("category") | |
| 58 | + .setFrontType(FRONT_TYPE) | |
| 59 | + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); | |
| 60 | + List<CodegenColumnDO> columns = getColumnList("category"); | |
| 61 | + | |
| 62 | + // 调用 | |
| 63 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 64 | + // 断言 | |
| 65 | + assertResult(result, "/vben5_ele_schema_tree"); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Test | |
| 69 | + public void testExecute_master_normal() { | |
| 70 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "/vben5_ele_schema_master_normal"); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Test | |
| 74 | + public void testExecute_master_erp() { | |
| 75 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_ERP, "/vben5_ele_schema_master_erp"); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Test | |
| 79 | + public void testExecute_master_inner() { | |
| 80 | + testExecute_master(CodegenTemplateTypeEnum.MASTER_INNER, "/vben5_ele_schema_master_inner"); | |
| 81 | + } | |
| 82 | + | |
| 83 | + private void testExecute_master(CodegenTemplateTypeEnum templateType, String path) { | |
| 84 | + // 准备参数 | |
| 85 | + CodegenTableDO table = getTable("student") | |
| 86 | + .setFrontType(FRONT_TYPE) | |
| 87 | + .setTemplateType(templateType.getType()); | |
| 88 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 89 | + // 准备参数(子表) | |
| 90 | + CodegenTableDO contactTable = getTable("contact") | |
| 91 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 92 | + .setFrontType(FRONT_TYPE) | |
| 93 | + .setSubJoinColumnId(100L).setSubJoinMany(true); | |
| 94 | + List<CodegenColumnDO> contactColumns = getColumnList("contact"); | |
| 95 | + // 准备参数(班主任) | |
| 96 | + CodegenTableDO teacherTable = getTable("teacher") | |
| 97 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) | |
| 98 | + .setFrontType(FRONT_TYPE) | |
| 99 | + .setSubJoinColumnId(200L).setSubJoinMany(false); | |
| 100 | + List<CodegenColumnDO> teacherColumns = getColumnList("teacher"); | |
| 101 | + | |
| 102 | + // 调用 | |
| 103 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, | |
| 104 | + Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns)); | |
| 105 | + // 断言 | |
| 106 | + assertResult(result, path); | |
| 107 | + } | |
| 108 | + | |
| 109 | +} | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue2Test.java
| ... | ... | @@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; |
| 5 | 5 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; |
| 6 | 6 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; |
| 7 | 7 | import com.baomidou.mybatisplus.annotation.DbType; |
| 8 | -import org.junit.jupiter.api.Disabled; | |
| 9 | 8 | import org.junit.jupiter.api.Test; |
| 10 | 9 | |
| 11 | 10 | import java.util.Arrays; |
| ... | ... | @@ -17,7 +16,6 @@ import java.util.Map; |
| 17 | 16 | * |
| 18 | 17 | * @author 芋道源码 |
| 19 | 18 | */ |
| 20 | -@Disabled | |
| 21 | 19 | public class CodegenEngineVue2Test extends CodegenEngineAbstractTest { |
| 22 | 20 | |
| 23 | 21 | @Test |
| ... | ... | @@ -37,6 +35,23 @@ public class CodegenEngineVue2Test extends CodegenEngineAbstractTest { |
| 37 | 35 | } |
| 38 | 36 | |
| 39 | 37 | @Test |
| 38 | + public void testExecute_vue2_one_importEnable() { | |
| 39 | + // 开启 import 开关 | |
| 40 | + codegenProperties.setImportEnable(true); | |
| 41 | + codegenEngine.initGlobalBindingMap(); | |
| 42 | + // 准备参数 | |
| 43 | + CodegenTableDO table = getTable("student") | |
| 44 | + .setFrontType(CodegenFrontTypeEnum.VUE2_ELEMENT_UI.getType()) | |
| 45 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 46 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 47 | + | |
| 48 | + // 调用 | |
| 49 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 50 | + // 断言 | |
| 51 | + assertResult(result, "/vue2_one_importEnable"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Test | |
| 40 | 55 | public void testExecute_vue2_tree() { |
| 41 | 56 | // 准备参数 |
| 42 | 57 | CodegenTableDO table = getTable("category") | ... | ... |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue3Test.java
| ... | ... | @@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; |
| 5 | 5 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; |
| 6 | 6 | import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; |
| 7 | 7 | import com.baomidou.mybatisplus.annotation.DbType; |
| 8 | -import org.junit.jupiter.api.Disabled; | |
| 9 | 8 | import org.junit.jupiter.api.Test; |
| 10 | 9 | |
| 11 | 10 | import java.util.Arrays; |
| ... | ... | @@ -17,7 +16,6 @@ import java.util.Map; |
| 17 | 16 | * |
| 18 | 17 | * @author 芋道源码 |
| 19 | 18 | */ |
| 20 | -@Disabled | |
| 21 | 19 | public class CodegenEngineVue3Test extends CodegenEngineAbstractTest { |
| 22 | 20 | |
| 23 | 21 | @Test |
| ... | ... | @@ -37,6 +35,23 @@ public class CodegenEngineVue3Test extends CodegenEngineAbstractTest { |
| 37 | 35 | } |
| 38 | 36 | |
| 39 | 37 | @Test |
| 38 | + public void testExecute_vue3_one_importEnable() { | |
| 39 | + // 开启 import 开关 | |
| 40 | + codegenProperties.setImportEnable(true); | |
| 41 | + codegenEngine.initGlobalBindingMap(); | |
| 42 | + // 准备参数 | |
| 43 | + CodegenTableDO table = getTable("student") | |
| 44 | + .setFrontType(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType()) | |
| 45 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | |
| 46 | + List<CodegenColumnDO> columns = getColumnList("student"); | |
| 47 | + | |
| 48 | + // 调用 | |
| 49 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | |
| 50 | + // 断言 | |
| 51 | + assertResult(result, "/vue3_one_importEnable"); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Test | |
| 40 | 55 | public void testExecute_vue3_tree() { |
| 41 | 56 | // 准备参数 |
| 42 | 57 | CodegenTableDO table = getTable("category") | ... | ... |
yudao-server/src/main/resources/application.yaml