diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/codegen/config/CodegenProperties.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/codegen/config/CodegenProperties.java index b764f5a..9baa4cc 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/codegen/config/CodegenProperties.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/codegen/config/CodegenProperties.java @@ -55,4 +55,10 @@ public class CodegenProperties { @NotNull(message = "是否生成单元测试不能为空") private Boolean unitTestEnable; + /** + * 是否生成 Excel 导入接口 + */ + @NotNull(message = "是否生成 Excel 导入接口不能为空") + private Boolean importEnable; + } diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index 9b55bd8..1ba0cd7 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -128,6 +128,8 @@ public class CodegenEngine { vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/form.vue"), vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/import.vue"), + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}ImportForm.vue")) .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑 vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) .put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑 @@ -166,6 +168,8 @@ public class CodegenEngine { vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/form.vue"), vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/import.vue"), + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("api/api.ts"), vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 @@ -183,6 +187,8 @@ public class CodegenEngine { vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/form.vue"), vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/import.vue"), + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("api/api.ts"), vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 @@ -202,6 +208,8 @@ public class CodegenEngine { vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/form.vue"), vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/import.vue"), + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("api/api.ts"), vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 @@ -219,6 +227,8 @@ public class CodegenEngine { vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/form.vue"), vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/import.vue"), + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/import-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("api/api.ts"), vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 @@ -286,6 +296,7 @@ public class CodegenEngine { globalBindingMap.put("jakartaPackage", jakartaEnable ? "jakarta" : "javax"); globalBindingMap.put("voType", codegenProperties.getVoType()); globalBindingMap.put("deleteBatchEnable", codegenProperties.getDeleteBatchEnable()); + globalBindingMap.put("importEnable", codegenProperties.getImportEnable()); // 全局 Java Bean globalBindingMap.put("CommonResultClassName", CommonResult.class.getName()); globalBindingMap.put("PageResultClassName", PageResult.class.getName()); @@ -345,6 +356,11 @@ public class CodegenEngine { if (!CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { return; } + } else if (isImportTemplate(vmPath)) { + // 关闭 import 时,跳过 ImportExcelVO / ImportRespVO 的生成 + if (!Boolean.TRUE.equals(codegenProperties.getImportEnable())) { + return; + } } // 2.3 默认生成 generateCode(result, vmPath, filePath, bindingMap); @@ -678,4 +694,9 @@ public class CodegenEngine { return path.contains("listReqVO"); } + private static boolean isImportTemplate(String path) { + return path.contains("importExcelVO") || path.contains("importRespVO") + || path.contains("views/import.vue"); + } + } diff --git a/yudao-module-infra/src/main/resources/codegen/java/controller/controller.vm b/yudao-module-infra/src/main/resources/codegen/java/controller/controller.vm index efe073d..c4e4086 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/controller/controller.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/controller/controller.vm @@ -1,7 +1,9 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}; import org.springframework.web.bind.annotation.*; +#if ($importEnable) import org.springframework.web.multipart.MultipartFile; +#end import ${jakartaPackage}.annotation.Resource; import org.springframework.validation.annotation.Validated; #if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end @@ -160,13 +162,14 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { BeanUtils.toBean(list, ${table.className}RespVO.class)); } #end +#if ($importEnable) @GetMapping("/get-import-template") @Operation(summary = "获得导入${table.classComment}模板") #if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:import')") #end - public void import${simpleClassName}Template(HttpServletResponse response) throws IOException { + public void importTemplate(HttpServletResponse response) throws IOException { ExcelUtils.write(response, "${table.classComment}导入模板.xls", "数据", ${sceneEnum.prefixClass}${table.className}ImportExcelVO.class, Collections.emptyList()); } @@ -177,11 +180,11 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { #if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:import')") #end - @ApiAccessLog(operateType = IMPORT) - public CommonResult<${sceneEnum.prefixClass}${table.className}ImportRespVO> import${simpleClassName}(@RequestParam("file") MultipartFile file) throws Exception { + public CommonResult<${sceneEnum.prefixClass}${table.className}ImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { List<${sceneEnum.prefixClass}${table.className}ImportExcelVO> list = ExcelUtils.read(file, ${sceneEnum.prefixClass}${table.className}ImportExcelVO.class); return success(${classNameVar}Service.import${simpleClassName}List(list)); } +#end ## 特殊:主子表专属逻辑 #foreach ($subTable in $subTables) diff --git a/yudao-module-infra/src/main/resources/codegen/java/service/service.vm b/yudao-module-infra/src/main/resources/codegen/java/service/service.vm index fda518c..66de005 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/service/service.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/service/service.vm @@ -25,6 +25,7 @@ public interface ${table.className}Service { * @return 编号 */ ${primaryColumn.javaType} create${simpleClassName}(@Valid ${saveReqVOClass} ${saveReqVOVar}); +#if ($importEnable) /** * 导入${table.classComment} @@ -33,6 +34,7 @@ public interface ${table.className}Service { * @return 导入结果 */ ${sceneEnum.prefixClass}${table.className}ImportRespVO import${simpleClassName}List(List<${sceneEnum.prefixClass}${table.className}ImportExcelVO> importList); +#end /** * 更新${table.classComment} diff --git a/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm b/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm index 215fecb..c73bd7c 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm @@ -7,7 +7,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; import java.util.*; +#if ($importEnable) import java.util.concurrent.atomic.AtomicInteger; +#end import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; ## 特殊:主子表专属逻辑 @@ -92,46 +94,32 @@ public class ${table.className}ServiceImpl implements ${table.className}Service // 返回 return ${classNameVar}.getId(); } +#if ($importEnable) @Override - @Transactional(rollbackFor = Exception.class) + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 public ${sceneEnum.prefixClass}${table.className}ImportRespVO import${simpleClassName}List(List<${sceneEnum.prefixClass}${table.className}ImportExcelVO> importList) { if (CollUtil.isEmpty(importList)) { return ${sceneEnum.prefixClass}${table.className}ImportRespVO.builder() - .successCount(0) - .failureCount(0) - .failureRows(new LinkedHashMap<>()) - .build(); + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); } - AtomicInteger successCount = new AtomicInteger(); - Map failureRows = new LinkedHashMap<>(); + // 遍历,逐个创建 + ${sceneEnum.prefixClass}${table.className}ImportRespVO respVO = ${sceneEnum.prefixClass}${table.className}ImportRespVO.builder() + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); AtomicInteger index = new AtomicInteger(1); importList.forEach(importItem -> { int currentIndex = index.getAndIncrement(); try { create${simpleClassName}(BeanUtils.toBean(importItem, ${saveReqVOClass}.class)); - successCount.incrementAndGet(); + respVO.setSuccessCount(respVO.getSuccessCount() + 1); } catch (Exception ex) { - failureRows.put(currentIndex, resolveImportFailureMessage(ex)); + respVO.getFailureRows().put(currentIndex, ex.getMessage()); } }); - return ${sceneEnum.prefixClass}${table.className}ImportRespVO.builder() - .successCount(successCount.get()) - .failureCount(failureRows.size()) - .failureRows(failureRows) - .build(); - } - - /** - * 仅返回根因异常信息,避免把 MyBatis 长堆栈直接暴露给前端。 - */ - private String resolveImportFailureMessage(Exception ex) { - Throwable root = ex; - while (root.getCause() != null && root.getCause() != root) { - root = root.getCause(); - } - return root.getMessage() != null ? root.getMessage() : ex.getMessage(); + respVO.setFailureCount(respVO.getFailureRows().size()); + return respVO; } +#end @Override ## 特殊:主子表专属逻辑(非 ERP 模式) diff --git a/yudao-module-infra/src/main/resources/codegen/sql/sql.vm b/yudao-module-infra/src/main/resources/codegen/sql/sql.vm index 82a5cb0..4d05660 100644 --- a/yudao-module-infra/src/main/resources/codegen/sql/sql.vm +++ b/yudao-module-infra/src/main/resources/codegen/sql/sql.vm @@ -1,6 +1,11 @@ ## 通用变量定义 +#if ($importEnable) #set ($functionNames = ['查询', '创建', '更新', '删除', '导出', '导入']) #set ($functionOps = ['query', 'create', 'update', 'delete', 'export', 'import']) +#else +#set ($functionNames = ['查询', '创建', '更新', '删除', '导出']) +#set ($functionOps = ['query', 'create', 'update', 'delete', 'export']) +#end ## ## 宏定义:生成按钮 SQL(通用部分) #macro(insertButtonSql $parentIdVar) diff --git a/yudao-module-infra/src/main/resources/codegen/vue/api/api.js.vm b/yudao-module-infra/src/main/resources/codegen/vue/api/api.js.vm index 80be3f4..4f61808 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue/api/api.js.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue/api/api.js.vm @@ -73,6 +73,7 @@ export function export${simpleClassName}Excel(params) { responseType: 'blob' }) } +#if ($importEnable) // 下载${table.classComment}导入模板 export function import${simpleClassName}Template() { @@ -91,6 +92,7 @@ export function import${simpleClassName}(data) { data }) } +#end ## 特殊:主子表专属逻辑 #foreach ($subTable in $subTables) #set ($index = $foreach.count - 1) diff --git a/yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm index 0f0cd9a..d687daa 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm @@ -49,6 +49,7 @@ 新增 +#if ($importEnable) 导入 @@ -57,6 +58,7 @@ 导入模板 +#end 导出 @@ -86,7 +88,9 @@ #end +#if ($importEnable) +#end ## 特殊:主子表专属逻辑 #if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 ) @@ -253,8 +257,10 @@ export default { loading: true, // 导出遮罩层 exportLoading: false, +#if ($importEnable) // 导入遮罩层 importLoading: false, +#end // 显示搜索条件 showSearch: true, ## 特殊:树表专属逻辑(树不需要分页接口) @@ -333,6 +339,7 @@ export default { openForm(id) { this.#[[$]]#refs["formRef"].open(id); }, +#if ($importEnable) /** 导入按钮操作 */ handleImport() { this.$refs.importFileRef && this.$refs.importFileRef.click(); @@ -369,6 +376,7 @@ export default { this.importLoading = false; } }, +#end /** 删除按钮操作 */ async handleDelete(row) { const ${primaryColumn.javaField} = row.${primaryColumn.javaField}; diff --git a/yudao-module-infra/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/src/main/resources/codegen/vue3/api/api.ts.vm index aeade85..6e875c5 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3/api/api.ts.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3/api/api.ts.vm @@ -98,6 +98,7 @@ export const ${simpleClassName}Api = { export${simpleClassName}: async (params) => { return await request.download({ url: `${baseURL}/export-excel`, params }) }, +#if ($importEnable) // 下载${table.classComment}导入模板 import${simpleClassName}Template: async () => { @@ -108,6 +109,7 @@ export const ${simpleClassName}Api = { import${simpleClassName}: async (data: FormData) => { return await request.upload({ url: `${baseURL}/import`, data }) }, +#end ## 特殊:主子表专属逻辑 #foreach ($subTable in $subTables) #set ($index = $foreach.count - 1) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3/views/import.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3/views/import.vue.vm new file mode 100644 index 0000000..fb0f3b5 --- /dev/null +++ b/yudao-module-infra/src/main/resources/codegen/vue3/views/import.vue.vm @@ -0,0 +1,103 @@ + + diff --git a/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm index c722f4c..54aa21a 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm @@ -92,6 +92,7 @@ > 新增 +#if ($importEnable) 导入 +#end +#if ($importEnable) - - - -
将文件拖到此处,或点击上传
- -
- -
+ <${simpleClassName}ImportForm ref="importRef" @success="getList" /> +#end <${simpleClassName}Form ref="formRef" @success="getList" /> @@ -308,7 +278,9 @@ import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' import { isEmpty } from '@/utils/is' import { dateFormatter } from '@/utils/formatTime' -import type { UploadUserFile } from 'element-plus' +#if ($importEnable) +import ${simpleClassName}ImportForm from './${simpleClassName}ImportForm.vue' +#end ## 特殊:树表专属逻辑 #if ( $table.templateType == 2 ) import { handleTree } from '@/utils/tree' @@ -354,10 +326,9 @@ const queryParams = reactive({ }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 -const importDialogVisible = ref(false) // 导入弹窗 -const importFormLoading = ref(false) // 导入的加载中 -const uploadRef = ref() -const fileList = ref([]) +#if ($importEnable) +const importRef = ref() // ${table.classComment} 导入组件的 Ref +#end /** 查询列表 */ const getList = async () => { @@ -394,58 +365,13 @@ const formRef = ref() const openForm = (type: string, id?: number) => { formRef.value.open(type, id) } +#if ($importEnable) /** 导入按钮操作 */ -const handleImport = async () => { - importDialogVisible.value = true - await resetImportForm() -} - -/** 提交导入 */ -const submitImportForm = async () => { - if (fileList.value.length === 0) { - message.error('请上传文件') - return - } - importFormLoading.value = true - try { - const formData = new FormData() - formData.append('file', fileList.value[0].raw as Blob) - const res = await ${simpleClassName}Api.import${simpleClassName}(formData) - const data = res.data - let text = '导入成功数量:' + data.successCount + ';导入失败数量:' + data.failureCount + ';' - if (data.failureCount > 0) { - for (const rowNo in data.failureRows) { - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >' - } - } - message.alert(text) - importDialogVisible.value = false - await getList() - } catch { - } finally { - importFormLoading.value = false - await resetImportForm() - } -} - -/** 下载导入模板 */ -const handleImportTemplate = async () => { - const data = await ${simpleClassName}Api.import${simpleClassName}Template() - download.excel(data, '${table.classComment}导入模板.xls') -} - -/** 导入文件超限 */ -const handleImportExceed = (): void => { - message.error('最多只能上传一个文件!') -} - -/** 重置导入表单 */ -const resetImportForm = async () => { - fileList.value = [] - await nextTick() - uploadRef.value?.clearFiles() +const handleImport = () => { + importRef.value.open() } +#end /** 删除按钮操作 */ const handleDelete = async (id: number) => { diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben/api/api.ts.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben/api/api.ts.vm index 3a46bcb..4042786 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben/api/api.ts.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben/api/api.ts.vm @@ -30,6 +30,7 @@ export function delete${simpleClassName}(id: number) { export function export${simpleClassName}(params) { return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls') } +#if ($importEnable) // 下载${table.classComment}导入模板 export function import${simpleClassName}Template() { @@ -40,3 +41,4 @@ export function import${simpleClassName}Template() { export function import${simpleClassName}(data: FormData) { return defHttp.post({ url: '${baseURL}/import', data }) } +#end diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben/views/index.vue.vm index 6fa5c7c..d435a6c 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben/views/index.vue.vm @@ -11,8 +11,10 @@ import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page, +#if ($importEnable) import${simpleClassName}, import${simpleClassName}Template, +#end } from '@/api/${table.moduleName}/${table.businessName}' defineOptions({ name: '${table.className}' }) @@ -20,8 +22,10 @@ defineOptions({ name: '${table.className}' }) const { t } = useI18n() const { createConfirm, createMessage } = useMessage() const [registerModal, { openModal }] = useModal() +#if ($importEnable) const importFileRef = ref() const importLoading = ref(false) +#end const [registerTable, { getForm, reload }] = useTable({ title: '${table.classComment}列表', @@ -57,6 +61,7 @@ async function handleExport() { }, }) } +#if ($importEnable) function handleImport() { importFileRef.value?.click() @@ -93,6 +98,7 @@ async function handleImportFileChange(event: Event) { importLoading.value = false } } +#end async function handleDelete(record: Recordable) { await delete${simpleClassName}(record.id) @@ -107,12 +113,14 @@ async function handleDelete(record: Recordable) { {{ t('action.create') }} +#if ($importEnable) 导入 导入模板 +#end {{ t('action.export') }} @@ -138,7 +146,9 @@ async function handleDelete(record: Recordable) { +#if ($importEnable) +#end <${simpleClassName}Modal @register="registerModal" @success="reload()" /> diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/api/api.ts.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/api/api.ts.vm index 6bcb4a2..c0139d4 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/api/api.ts.vm +++ b/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[]) { export function export${simpleClassName}(params: any) { return requestClient.download('${baseURL}/export-excel', { params }); } +#if ($importEnable) /** 下载${table.classComment}导入模板 */ export function import${simpleClassName}Template() { @@ -110,6 +111,7 @@ export function import${simpleClassName}Template() { export function import${simpleClassName}(data: FormData) { return requestClient.post('${baseURL}/import', data); } +#end ## 特殊:主子表专属逻辑 #foreach ($subTable in $subTables) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/import.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/import.vue.vm new file mode 100644 index 0000000..e4e52b4 --- /dev/null +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/import.vue.vm @@ -0,0 +1,71 @@ + + + diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm index 8159ad7..befa027 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm @@ -27,9 +27,12 @@ import { getRangePickerDefaultProps } from '#/utils/rangePickerProps'; import { $t } from '#/locales'; #if (${table.templateType} == 2)## 树表接口 import { handleTree } from '@vben/utils' -import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName}, import${simpleClassName}, import${simpleClassName}Template } from '#/api/${table.moduleName}/${table.businessName}'; +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; #else## 标准表接口 -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}'; +import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; +#end +#if ($importEnable) +import ${simpleClassName}Import from './modules/import-form.vue'; #end #if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况 @@ -73,8 +76,6 @@ const queryParams = reactive({ }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 -const importLoading = ref(false) // 导入的加载中 -const importFileRef = ref() /** 查询列表 */ async function getList() { @@ -121,6 +122,17 @@ const [FormModal, formModalApi] = useVbenModal({ connectedComponent: ${simpleClassName}Form, destroyOnClose: true, }); +#if ($importEnable) +const [ImportFormModal, importFormModalApi] = useVbenModal({ + connectedComponent: ${simpleClassName}Import, + destroyOnClose: true, +}); + +/** 导入${table.classComment} */ +function handleImport() { + importFormModalApi.open(); +} +#end /** 创建${table.classComment} */ function handleCreate() { @@ -192,43 +204,6 @@ try { } } -/** 导入模板下载 */ -async function handleImportTemplateDownload() { - const data = await import${simpleClassName}Template(); - downloadFileFromBlobPart({ fileName: '${table.classComment}导入模板.xls', source: data }); -} - -/** 导入按钮操作 */ -function handleImport() { - importFileRef.value?.click(); -} - -/** 导入文件变更 */ -async function handleImportFileChange(event: Event) { - const target = event.target as HTMLInputElement; - const file = target.files?.[0]; - if (!file) { - return; - } - importLoading.value = true; - try { - const formData = new FormData(); - formData.append('file', file); - const response: any = await import${simpleClassName}(formData); - const data = response?.data ?? response ?? {}; - let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; - if (data.failureRows) { - Object.keys(data.failureRows).forEach((rowNo) => { - text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; - }); - } - message.info(text); - await getList(); - } finally { - target.value = ''; - importLoading.value = false; - } -} #if (${table.templateType} == 2) /** 切换树形展开/收缩状态 */ @@ -249,7 +224,9 @@ onMounted(() => {