From a1b1a8a318649bd61c92006fa1822471802b2d5b Mon Sep 17 00:00:00 2001
From: yangjie <717642468@qq.com>
Date: Sun, 3 Nov 2024 22:00:10 +0800
Subject: [PATCH] CRUD-PLUS
---
.../.idea/JavaSceneConfigState.xml" | 6 +
.../.idea/compiler.xml" | 22 +
.../.idea/encodings.xml" | 9 +
.../.idea/jarRepositories.xml" | 20 +
.../.idea/misc.xml" | 15 +
.../.idea/uiDesigner.xml" | 124 +
.../.idea/vcs.xml" | 6 +
.../.idea/workspace.xml" | 434 +
.../LICENSE" | 165 +
.../README.md" | 67 +
.../crud-plus/pom.xml" | 113 +
.../yang/crudplus/CrudPlusApplication.java" | 17 +
.../common/apo/ExceptionHandlerAspect.java" | 35 +
.../crudplus/common/config/GenConfig.java" | 73 +
.../common/config/MybatisPlusConfig.java" | 24 +
.../crudplus/common/config/WebConfig.java" | 19 +
.../common/constant/GenConstants.java" | 119 +
.../common/exception/CustomException.java" | 18 +
.../exception/GlobalExceptionHandler.java" | 40 +
.../exception/ValidationException.java" | 30 +
.../crudplus/common/text/StrFormatter.java" | 124 +
.../yang/crudplus/common/utils/GenUtils.java" | 249 +
.../common/utils/GenericConverter.java" | 55 +
.../crudplus/common/utils/StringUtils.java" | 670 ++
.../crudplus/common/utils/TypeChecker.java" | 54 +
.../common/utils/VelocityInitializer.java" | 36 +
.../crudplus/common/utils/VelocityUtils.java" | 366 +
.../crudplus/controller/TableContrller.java" | 180 +
.../controller/TableFunctionController.java" | 145 +
.../mapper/GenTableColumnMapper.java" | 61 +
.../yang/crudplus/mapper/GenTableMapper.java" | 134 +
.../mapper/TableFunctionColumnMapper.java" | 10 +
.../crudplus/mapper/TableFunctionMapper.java" | 55 +
.../org/yang/crudplus/pojo/GenTable.java" | 108 +
.../yang/crudplus/pojo/GenTableColumn.java" | 156 +
.../yang/crudplus/pojo/TableFunction.java" | 63 +
.../crudplus/pojo/TableFunctionColumn.java" | 73 +
.../yang/crudplus/pojo/req/GenTableReq.java" | 33 +
.../crudplus/pojo/req/GenTableSaveReq.java" | 53 +
.../pojo/req/TableFunctionListReq.java" | 24 +
.../pojo/req/TableFunnctionSaveReq.java" | 75 +
.../org/yang/crudplus/pojo/req/testReq.java" | 15 +
.../pojo/resp/CustomReqRespList.java" | 23 +
.../crudplus/pojo/resp/GenTableListResp.java" | 13 +
.../crudplus/pojo/resp/GenTableResp.java" | 30 +
.../pojo/resp/GenTablesUpdateResp.java" | 25 +
.../yang/crudplus/pojo/resp/Response.java" | 31 +
.../pojo/resp/TableFunctionListResp.java" | 29 +
.../pojo/resp/TableFunctionResp.java" | 54 +
.../pojo/resp/TableFunnctionSaveResp.java" | 74 +
.../yang/crudplus/pojo/vo/GenTableCRUD.java" | 127 +
.../crudplus/pojo/vo/GenTableColumnbVo.java" | 106 +
.../pojo/vo/TableFunctionPlusVo.java" | 86 +
.../crudplus/service/GenTableService.java" | 97 +
.../service/ITableFunctionColumnService.java" | 15 +
.../service/ITableFunctionService.java" | 65 +
.../service/impl/GenTableServiceImpl.java" | 340 +
.../impl/TableFunctionColumnServiceImpl.java" | 20 +
.../impl/TableFunctionServiceImpl.java" | 524 +
.../main/resources/application.properties" | 3 +
.../src/main/resources/application.yml" | 29 +
.../src/main/resources/generator.yml" | 10 +
.../crud-plus/src/main/resources/logback.xml" | 16 +
.../resources/vm/java/controller.java.vm" | 74 +
.../main/resources/vm/java/domain.java.vm" | 69 +
.../main/resources/vm/java/mapper.java.vm" | 67 +
.../src/main/resources/vm/java/req.java.vm" | 16 +
.../src/main/resources/vm/java/resp.java.vm" | 16 +
.../main/resources/vm/java/service.java.vm" | 86 +
.../resources/vm/java/serviceImpl.java.vm" | 258 +
.../resources/vm/java/sub-domain.java.vm" | 76 +
.../src/main/resources/vm/xml/mapper.xml.vm" | 124 +
.../crudplus/CrudPlusApplicationTests.java" | 13 +
.../crud-test/pom.xml" | 78 +
.../yang/crudplus/CrudTestApplication.java" | 18 +
.../controller/StudentsController.java" | 74 +
.../org/yang/crudplus/domain/Students.java" | 84 +
.../domain/req/deletcStudengtsReq.java" | 14 +
.../domain/req/insertStudentsReq.java" | 26 +
.../domain/req/selectStudentByIdReq.java" | 14 +
.../crudplus/domain/req/updateByAgeReq.java" | 14 +
.../domain/resp/selectStudentByIdResp.java" | 26 +
.../domain/resp/updateByAgeResp.java" | 26 +
.../yang/crudplus/mapper/StudentsMapper.java" | 63 +
.../crudplus/service/StudentsService.java" | 111 +
.../service/impl/StudentsServiceImpl.java" | 193 +
.../src/main/resources/application.yml" | 18 +
.../mapper/crudplus/StudentsMapper.xml" | 121 +
.../crudtest/CrudTestApplicationTests.java" | 14 +
.../image/img.png" | Bin 0 -> 22906 bytes
.../image/img_-1.png" | Bin 0 -> 41679 bytes
.../image/img_1.png" | Bin 0 -> 47540 bytes
.../image/img_2.png" | Bin 0 -> 89592 bytes
.../image/img_3.png" | Bin 0 -> 38596 bytes
.../image/img_4.png" | Bin 0 -> 15393 bytes
.../image/img_5.png" | Bin 0 -> 30529 bytes
.../image/img_7.png" | Bin 0 -> 36603 bytes
.../image/img_8.png" | Bin 0 -> 53514 bytes
.../pom.xml" | 59 +
.../sql/crud.sql" | 160 +
.../vue-crud/vue-crud/.env.development" | 1 +
.../vue-crud/vue-crud/.env.production" | 1 +
.../vue-crud/vue-crud/.eslintignore" | 22 +
.../vue-crud/vue-crud/.eslintrc.cjs" | 19 +
.../vue-crud/vue-crud/.gitignore" | 28 +
.../vue-crud/vue-crud/.npmrc" | 2 +
.../vue-crud/vue-crud/.prettierrc.cjs" | 29 +
.../vue-crud/.vscode/extensions.json" | 3 +
.../vue-crud/vue-crud/README.md" | 20 +
.../vue-crud/vue-crud/components.d.ts" | 35 +
.../vue-crud/vue-crud/index.html" | 14 +
.../vue-crud/vue-crud/package-lock.json" | 9911 +++++++++++++++++
.../vue-crud/vue-crud/package.json" | 59 +
.../vue-crud/vue-crud/public/favicon.ico" | Bin 0 -> 16958 bytes
.../vue-crud/vue-crud/src/App.vue" | 14 +
.../vue-crud/vue-crud/src/api/genTables.ts" | 27 +
.../vue-crud/src/api/genTablesPlus.ts" | 79 +
.../vue-crud/vue-crud/src/api/interface.ts" | 10 +
.../vue-crud/vue-crud/src/api/table.ts" | 50 +
.../vue-crud/vue-crud/src/assets/404.png" | Bin 0 -> 51678 bytes
.../src/components/codemirror/CodeMirror.vue" | 56 +
.../src/components/svg-icon/index.ts" | 4 +
.../src/components/svg-icon/src/svg-icon.vue" | 40 +
.../vue-crud/vue-crud/src/hooks/index.ts" | 195 +
.../vue-crud/vue-crud/src/hooks/interface.ts" | 35 +
.../vue-crud/src/icons/iconfont/iconfont.js" | 1 +
.../vue-crud/vue-crud/src/icons/svg/404.svg" | 1 +
.../vue-crud/src/icons/svg/gitee.svg" | 2 +
.../components/Navbar/components/Logo.vue" | 27 +
.../src/layout/components/Navbar/index.vue" | 64 +
.../layout/components/Router/Redirect.vue" | 18 +
.../components/Sidebar/components/Menu.vue" | 21 +
.../Sidebar/components/MenuItem.vue" | 24 +
.../src/layout/components/Sidebar/index.vue" | 9 +
.../vue-crud/vue-crud/src/layout/index.vue" | 25 +
.../vue-crud/vue-crud/src/main.ts" | 28 +
.../vue-crud/vue-crud/src/router/index.ts" | 64 +
.../vue-crud/src/styles/element.scss" | 97 +
.../vue-crud/vue-crud/src/styles/index.scss" | 3 +
.../vue-crud/vue-crud/src/styles/layout.scss" | 67 +
.../vue-crud/src/styles/variables.scss" | 20 +
.../vue-crud/vue-crud/src/types/shims.d.ts" | 13 +
.../vue-crud/vue-crud/src/utils/request.ts" | 51 +
.../vue-crud/vue-crud/src/utils/tool.ts" | 45 +
.../vue-crud/vue-crud/src/views/404.vue" | 32 +
.../addfunction/addFunction.vue" | 364 +
.../addfunction/tableFunction.vue" | 202 +
.../generator-plus/addfunction/tableInfo.vue" | 95 +
.../addfunction/tableRequest.vue" | 126 +
.../addfunction/tableResponse.vue" | 122 +
.../src/views/generator-plus/edit.vue" | 346 +
.../src/views/generator-plus/index.vue" | 230 +
.../src/views/generator/TableInfoForm.vue" | 145 +
.../src/views/generator/basicInfoForm.vue" | 100 +
.../vue-crud/src/views/generator/edit.vue" | 158 +
.../vue-crud/src/views/generator/import.vue" | 123 +
.../vue-crud/src/views/generator/index.vue" | 184 +
.../vue-crud/src/views/generator/preview.vue" | 37 +
.../vue-crud/vue-crud/tsconfig.json" | 30 +
.../vue-crud/vue-crud/vite.config.ts" | 28 +
160 files changed, 21280 insertions(+)
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/JavaSceneConfigState.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/compiler.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/encodings.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/jarRepositories.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/misc.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/uiDesigner.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/vcs.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/workspace.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/LICENSE"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/README.md"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/pom.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/CrudPlusApplication.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/apo/ExceptionHandlerAspect.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/GenConfig.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/MybatisPlusConfig.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/WebConfig.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/constant/GenConstants.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/CustomException.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/GlobalExceptionHandler.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/ValidationException.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/text/StrFormatter.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenUtils.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenericConverter.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/StringUtils.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/TypeChecker.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityInitializer.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityUtils.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableContrller.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableFunctionController.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableColumnMapper.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableMapper.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionColumnMapper.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionMapper.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTable.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTableColumn.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunction.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunctionColumn.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableSaveReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunctionListReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunnctionSaveReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/testReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/CustomReqRespList.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableListResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTablesUpdateResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/Response.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionListResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunnctionSaveResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableCRUD.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableColumnbVo.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/TableFunctionPlusVo.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/GenTableService.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionColumnService.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionService.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/GenTableServiceImpl.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionColumnServiceImpl.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionServiceImpl.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.properties"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.yml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/generator.yml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/logback.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/controller.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/domain.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/mapper.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/req.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/resp.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/service.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/serviceImpl.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/sub-domain.java.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/xml/mapper.xml.vm"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/test/java/org/yang/crudplus/CrudPlusApplicationTests.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/pom.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/CrudTestApplication.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/controller/StudentsController.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/Students.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/deletcStudengtsReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/insertStudentsReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/selectStudentByIdReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/updateByAgeReq.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/selectStudentByIdResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/updateByAgeResp.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/mapper/StudentsMapper.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/StudentsService.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/impl/StudentsServiceImpl.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/application.yml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/mapper/crudplus/StudentsMapper.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/test/java/org/yang/crudtest/CrudTestApplicationTests.java"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_-1.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_1.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_2.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_3.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_4.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_5.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_7.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img_8.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/pom.xml"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/sql/crud.sql"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.env.development"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.env.production"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.eslintignore"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.eslintrc.cjs"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.gitignore"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.npmrc"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.prettierrc.cjs"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/.vscode/extensions.json"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/README.md"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/components.d.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/index.html"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/package-lock.json"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/package.json"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/public/favicon.ico"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/App.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/api/genTables.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/api/genTablesPlus.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/api/interface.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/api/table.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/assets/404.png"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/components/codemirror/CodeMirror.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/components/svg-icon/index.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/components/svg-icon/src/svg-icon.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/hooks/index.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/hooks/interface.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/icons/iconfont/iconfont.js"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/icons/svg/404.svg"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/icons/svg/gitee.svg"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/components/Navbar/components/Logo.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/components/Navbar/index.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/components/Router/Redirect.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/components/Sidebar/components/Menu.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/components/Sidebar/components/MenuItem.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/components/Sidebar/index.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/layout/index.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/main.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/router/index.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/styles/element.scss"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/styles/index.scss"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/styles/layout.scss"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/styles/variables.scss"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/types/shims.d.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/utils/request.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/utils/tool.ts"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/404.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/addfunction/addFunction.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/addfunction/tableFunction.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/addfunction/tableInfo.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/addfunction/tableRequest.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/addfunction/tableResponse.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/edit.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator-plus/index.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator/TableInfoForm.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator/basicInfoForm.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator/edit.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator/import.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator/index.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/src/views/generator/preview.vue"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/tsconfig.json"
create mode 100644 "CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/vue-crud/vue-crud/vite.config.ts"
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/JavaSceneConfigState.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/JavaSceneConfigState.xml"
new file mode 100644
index 0000000..a8442f4
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/JavaSceneConfigState.xml"
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/compiler.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/compiler.xml"
new file mode 100644
index 0000000..a46bfe0
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/compiler.xml"
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/encodings.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/encodings.xml"
new file mode 100644
index 0000000..00f6c6b
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/encodings.xml"
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/jarRepositories.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/jarRepositories.xml"
new file mode 100644
index 0000000..abb532a
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/jarRepositories.xml"
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/misc.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/misc.xml"
new file mode 100644
index 0000000..6ecd755
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/misc.xml"
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/uiDesigner.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/uiDesigner.xml"
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/uiDesigner.xml"
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/vcs.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/vcs.xml"
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/vcs.xml"
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/workspace.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/workspace.xml"
new file mode 100644
index 0000000..578dd1c
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/.idea/workspace.xml"
@@ -0,0 +1,434 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "associatedIndex": 7
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1729760664387
+
+
+ 1729760664387
+
+
+
+
+
+
+
+
+
+ 1729761307634
+
+
+
+ 1729761307634
+
+
+
+ 1729847771066
+
+
+
+ 1729847771066
+
+
+
+ 1729861347384
+
+
+
+ 1729861347384
+
+
+
+ 1729867640009
+
+
+
+ 1729867640009
+
+
+
+ 1729871811653
+
+
+
+ 1729871811653
+
+
+
+ 1729874309948
+
+
+
+ 1729874309948
+
+
+
+ 1729956884068
+
+
+
+ 1729956884068
+
+
+
+ 1729960419129
+
+
+
+ 1729960419129
+
+
+
+ 1730019385489
+
+
+
+ 1730019385489
+
+
+
+ 1730023743112
+
+
+
+ 1730023743112
+
+
+
+ 1730046679930
+
+
+
+ 1730046679930
+
+
+
+ 1730125789961
+
+
+
+ 1730125789961
+
+
+
+ 1730199684927
+
+
+
+ 1730199684927
+
+
+
+ 1730256622256
+
+
+
+ 1730256622256
+
+
+
+ 1730301003368
+
+
+
+ 1730301003368
+
+
+
+ 1730342107683
+
+
+
+ 1730342107683
+
+
+
+ 1730348556822
+
+
+
+ 1730348556822
+
+
+
+ 1730390046859
+
+
+
+ 1730390046859
+
+
+
+ 1730449392037
+
+
+
+ 1730449392038
+
+
+
+ 1730479578366
+
+
+
+ 1730479578366
+
+
+
+ 1730520292999
+
+
+
+ 1730520292999
+
+
+
+ 1730534006122
+
+
+
+ 1730534006122
+
+
+
+ 1730540333598
+
+
+
+ 1730540333598
+
+
+
+ 1730561304174
+
+
+
+ 1730561304174
+
+
+
+ 1730620652839
+
+
+
+ 1730620652839
+
+
+
+ 1730626234971
+
+
+
+ 1730626234971
+
+
+
+ 1730626767645
+
+
+
+ 1730626767645
+
+
+
+ 1730629991174
+
+
+
+ 1730629991174
+
+
+
+ 1730631542253
+
+
+
+ 1730631542253
+
+
+
+ 1730631611245
+
+
+
+ 1730631611245
+
+
+
+ 1730639667797
+
+
+
+ 1730639667797
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/LICENSE" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/LICENSE"
new file mode 100644
index 0000000..0a04128
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/LICENSE"
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/README.md" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/README.md"
new file mode 100644
index 0000000..a2302d2
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/README.md"
@@ -0,0 +1,67 @@
+# CRUD-PLUS
+
+## 站在巨人的肩膀上做CRUD
+### 广告
+25届应届毕业生,目前积极找工作中!主后端Java开发,前端基础也还行,业务有需求可转方向!有项目企业实习经历!可实习!意向广东发展!
+有大佬能内推的可以issue我联系您,或者我的wx:**Print_15520182404** 感谢!!!!
+
+#### 介绍
+开发本项目是因为在实习期间,遇到新的业务开发,每次都需要做单表的CRUD代码,当表数量很多的时候,即使使用代码生成插件也会有一些方法无法生成,代码生成大多基于数据库实体类进行操作,但是在实际开发中,
+会跟据业务请求不同封装单独的req和resp,重复代码太多,开发效率低,因此萌生了开发了CRUD-PLUS的想法。
+
+CRUD-PLUS是一款低代码生成器,可跟据模板内容自定义生成单表 的CRUD代码,同时支持自定义方法 的service和serviceImpl和req,resp的生成,让开发者专注于业务逻辑的处理
+项目引入了Mybatis-Plus,可快速实现单表增删改查。
+
+在此特别感谢
+[若依/RuoYi](https://gitee.com/y_project/RuoYi)
+[MAKU/maku-generator](https://gitee.com/makunet/maku-generator)
+后端的单表CRUD开发是基于[若依/RuoYi](https://gitee.com/y_project/RuoYi)的代码生成模块进行开发
+前端界面是基于[MAKU/maku-generator](https://gitee.com/makunet/maku-generator)进行二次开发
+因此十分感谢这两个开源项目,感谢!
+
+**注意:**
+项目当中依旧还存在一些不完善的地方,欢迎大家提issue,会尽力修复!
+也欢迎大家fork进行自定义二次开发,有疑问可通过issue提问,
+
+#### 项目特点
+
+**单表:**
+1. 单表domain,service,serviceImp,controller,mapper,xml的生成
+2. 单表req,resp的生成
+3. 基于req和resp的自定义方法,service,serviceImpl的生成
+
+**联表:**
+todo 等待后续开发
+
+### 项目结构
+
+后端采用springboot3、mybatis-plus、mybatis、lombok等
+前端采用vue3、element-plus、ts等
+详情可参考[若依/RuoYi](https://gitee.com/y_project/RuoYi)和
+[MAKU/maku-generator](https://gitee.com/makunet/maku-generator)
+#### 本地启动
+1. clone项目到本地,导入数据库
+2. 加载maven配置,并修改数据库链接
+3. 前端下载依赖
+4. 后端项目启动,前端项目启动
+
+#### 使用说明
+- 如果使用自定义方法,可能会存在生成的方法返回类不符合的情况,需要自行修改,
+比如方法返回设置为void,但是方法是新增方法,方法默认返回新增操作影响行数,需要自行修改
+- 在创建自定义方法的时候,如果之前已经创建过了方法,那么在创建方法的最终选择请求类和响应类可选择之前创建的方法中的请求类或者响应类实现**复用**
+- 在定义响应类的时候可以输入你的系统中存在的响应类,或Long,String,void等方法返回类
+- 默认查询查询返回的是一个集合List
+- 存在以上情况需要手动进行修改一些代码
+
+
+
+### 效果图
+
+
+
+
+
+
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/pom.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/pom.xml"
new file mode 100644
index 0000000..e40b48e
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/pom.xml"
@@ -0,0 +1,113 @@
+
+
+ 4.0.0
+
+ org.yang
+ crud
+ 0.0.1-SNAPSHOT
+ ../../crud/pom.xml
+
+
+ org.yang
+ CRUD-PLUS
+ 0.0.1-SNAPSHOT
+ CRUD-PLUS
+ CRUD-PLUS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ 3.5.7
+
+
+ org.projectlombok
+ lombok
+ 1.18.24
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ commons-io
+ commons-io
+ 2.16.1
+
+
+ org.apache.velocity
+ velocity-engine-core
+ 2.3
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.43
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/CrudPlusApplication.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/CrudPlusApplication.java"
new file mode 100644
index 0000000..a492c95
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/CrudPlusApplication.java"
@@ -0,0 +1,17 @@
+package org.yang.crudplus;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@SpringBootApplication
+@MapperScan("org.yang.crudplus.mapper")
+@EnableTransactionManagement
+public class CrudPlusApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CrudPlusApplication.class, args);
+ }
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/apo/ExceptionHandlerAspect.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/apo/ExceptionHandlerAspect.java"
new file mode 100644
index 0000000..9585a2d
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/apo/ExceptionHandlerAspect.java"
@@ -0,0 +1,35 @@
+package org.yang.crudplus.common.apo;
+
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+import org.yang.crudplus.common.exception.CustomException;
+import org.yang.crudplus.common.exception.ValidationException;
+import org.yang.crudplus.pojo.resp.Response;
+
+@Aspect
+@Component
+@Slf4j
+public class ExceptionHandlerAspect {
+
+ @Around("execution(* org.yang.crudplus.controller..*(..))")
+ public Object handleControllerMethod(ProceedingJoinPoint pjp) {
+ try {
+ // 执行目标方法
+ return pjp.proceed();
+ } catch (CustomException e) {
+ log.error("异常抛出: " + e.getMessage(), e);
+ return new Response<>(e.getCode(), e.getMessage());
+ } catch (ValidationException e) {
+ log.error("参数校验异常: " + e.getMessage(), e);
+ return new Response<>(e.getCode(), e.getMessage());
+ } catch (Throwable e) {
+ log.error("Unexpected Exception: " + e.getMessage(), e);
+ return new Response<>(500, "服务异常");
+ }
+
+ }
+}
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/GenConfig.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/GenConfig.java"
new file mode 100644
index 0000000..6dfa0c9
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/GenConfig.java"
@@ -0,0 +1,73 @@
+package org.yang.crudplus.common.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取代码生成相关配置
+ *
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "gen")
+@PropertySource(value = { "classpath:generator.yml" })
+public class GenConfig
+{
+ /** 作者 */
+ public static String author;
+
+ /** 生成包路径 */
+ public static String packageName;
+
+ /** 自动去除表前缀,默认是false */
+ public static boolean autoRemovePre;
+
+ /** 表前缀(类名不会包含表前缀) */
+ public static String tablePrefix;
+
+ public static String getAuthor()
+ {
+ return author;
+ }
+
+ @Value("${author}")
+ public void setAuthor(String author)
+ {
+ GenConfig.author = author;
+ }
+
+ public static String getPackageName()
+ {
+ return packageName;
+ }
+
+ @Value("${packageName}")
+ public void setPackageName(String packageName)
+ {
+ GenConfig.packageName = packageName;
+ }
+
+ public static boolean getAutoRemovePre()
+ {
+ return autoRemovePre;
+ }
+
+ @Value("${autoRemovePre}")
+ public void setAutoRemovePre(boolean autoRemovePre)
+ {
+ GenConfig.autoRemovePre = autoRemovePre;
+ }
+
+ public static String getTablePrefix()
+ {
+ return tablePrefix;
+ }
+
+ @Value("${tablePrefix}")
+ public void setTablePrefix(String tablePrefix)
+ {
+ GenConfig.tablePrefix = tablePrefix;
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/MybatisPlusConfig.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/MybatisPlusConfig.java"
new file mode 100644
index 0000000..8259965
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/MybatisPlusConfig.java"
@@ -0,0 +1,24 @@
+package org.yang.crudplus.common.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@MapperScan("org.yang.crudplus.mapper")
+public class MybatisPlusConfig {
+
+ /**
+ * 添加分页插件
+ */
+ @Bean
+ public MybatisPlusInterceptor mybatisPlusInterceptor() {
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
+ // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
+ return interceptor;
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/WebConfig.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/WebConfig.java"
new file mode 100644
index 0000000..249bf64
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/config/WebConfig.java"
@@ -0,0 +1,19 @@
+package org.yang.crudplus.common.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**")
+ .allowedOrigins("http://localhost:3000") // 允许的前端地址
+ .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+ .allowedHeaders("*")
+ .allowCredentials(true);
+ }
+}
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/constant/GenConstants.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/constant/GenConstants.java"
new file mode 100644
index 0000000..3751cf4
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/constant/GenConstants.java"
@@ -0,0 +1,119 @@
+package org.yang.crudplus.common.constant;
+
+/**
+ * 代码生成通用常量
+ *
+ * @author ruoyi
+ */
+public class GenConstants
+{
+ /** 单表(增删改查) */
+ public static final String TPL_CRUD = "crud";
+
+ public static final String UTF_8 = "UTF-8";
+
+ /** 树表(增删改查) */
+ public static final String TPL_TREE = "tree";
+
+ /** 主子表(增删改查) */
+ public static final String TPL_SUB = "sub";
+
+ /** 树编码字段 */
+ public static final String TREE_CODE = "treeCode";
+
+ /** 树父编码字段 */
+ public static final String TREE_PARENT_CODE = "treeParentCode";
+
+ /** 树名称字段 */
+ public static final String TREE_NAME = "treeName";
+
+ /** 上级菜单ID字段 */
+ public static final String PARENT_MENU_ID = "parentMenuId";
+
+ /** 上级菜单名称字段 */
+ public static final String PARENT_MENU_NAME = "parentMenuName";
+
+ /** 数据库字符串类型 */
+ public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
+
+ /** 数据库文本类型 */
+ public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
+
+ /** 数据库时间类型 */
+ public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+ /** 数据库数字类型 */
+ public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+ "bit", "bigint", "float", "double", "decimal" };
+
+ /** 页面不需要编辑字段 */
+ public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+ /** 页面不需要显示的列表字段 */
+ public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time" };
+
+ /** 页面不需要查询字段 */
+ public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time", "remark" };
+
+ /** Entity基类字段 */
+ public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
+
+ /** Tree基类字段 */
+ public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
+
+ /** 文本框 */
+ public static final String HTML_INPUT = "input";
+
+ /** 文本域 */
+ public static final String HTML_TEXTAREA = "textarea";
+
+ /** 下拉框 */
+ public static final String HTML_SELECT = "select";
+
+ /** 单选框 */
+ public static final String HTML_RADIO = "radio";
+
+ /** 复选框 */
+ public static final String HTML_CHECKBOX = "checkbox";
+
+ /** 日期控件 */
+ public static final String HTML_DATETIME = "datetime";
+
+ /** 图片上传控件 */
+ public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+ /** 文件上传控件 */
+ public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+ /** 富文本控件 */
+ public static final String HTML_EDITOR = "editor";
+
+ /** 字符串类型 */
+ public static final String TYPE_STRING = "String";
+
+ /** 整型 */
+ public static final String TYPE_INTEGER = "Integer";
+
+ /** 长整型 */
+ public static final String TYPE_LONG = "Long";
+
+ /** 浮点型 */
+ public static final String TYPE_DOUBLE = "Double";
+
+ /** 高精度计算类型 */
+ public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+ /** 时间类型 */
+ public static final String TYPE_DATE = "Date";
+
+ /** 模糊查询 */
+ public static final String QUERY_LIKE = "LIKE";
+
+ /** 相等查询 */
+ public static final String QUERY_EQ = "EQ";
+
+ /** 需要 */
+ public static final String REQUIRE = "1";
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/CustomException.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/CustomException.java"
new file mode 100644
index 0000000..f1431ce
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/CustomException.java"
@@ -0,0 +1,18 @@
+package org.yang.crudplus.common.exception;
+
+public class CustomException extends RuntimeException {
+ private int code;
+
+ public CustomException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/GlobalExceptionHandler.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/GlobalExceptionHandler.java"
new file mode 100644
index 0000000..9f8efd6
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/GlobalExceptionHandler.java"
@@ -0,0 +1,40 @@
+package org.yang.crudplus.common.exception;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.yang.crudplus.pojo.resp.Response;
+
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+ @ExceptionHandler(CustomException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public Response handleCustomException(CustomException e) {
+ log.error("CustomException: " + e.getMessage(), e);
+ return new Response<>(e.getCode(), e.getMessage());
+ }
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public Response handleValidationException(MethodArgumentNotValidException e) {
+ log.error("ValidationException: " + e.getMessage(), e);
+ StringBuilder errors = new StringBuilder();
+ e.getBindingResult().getAllErrors().forEach(error -> {
+ errors.append(error.getDefaultMessage()).append(";");
+ });
+ return new Response<>(400, errors.toString());
+ }
+
+ @ExceptionHandler(Exception.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public Response handleException(Exception e) {
+ log.error("Unexpected Exception: " + e.getMessage(), e);
+ return new Response<>(500, "Internal Server Error");
+ }
+}
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/ValidationException.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/ValidationException.java"
new file mode 100644
index 0000000..cbe4c0b
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/exception/ValidationException.java"
@@ -0,0 +1,30 @@
+package org.yang.crudplus.common.exception;
+
+public class ValidationException extends RuntimeException {
+ private int code;
+ private String message;
+
+ public ValidationException(String message) {
+ super(message);
+ this.code = 400; // HTTP 400 Bad Request
+ this.message = message;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/text/StrFormatter.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/text/StrFormatter.java"
new file mode 100644
index 0000000..d92191f
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/text/StrFormatter.java"
@@ -0,0 +1,124 @@
+package org.yang.crudplus.common.text;
+
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.yang.crudplus.common.utils.StringUtils;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+import static org.yang.crudplus.common.constant.GenConstants.UTF_8;
+
+/**
+ * 字符串格式化
+ *
+ * @author ruoyi
+ */
+public class StrFormatter {
+ public static final String EMPTY_JSON = "{}";
+ public static final char C_BACKSLASH = '\\';
+ public static final char C_DELIM_START = '{';
+ public static final char C_DELIM_END = '}';
+
+
+ public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+
+
+ /**
+ * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ *
+ * @param strPattern 字符串模板
+ * @param argArray 参数列表
+ * @return 结果
+ */
+ public static String format(final String strPattern, final Object... argArray) {
+ if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) {
+ return strPattern;
+ }
+ final int strPatternLength = strPattern.length();
+
+ // 初始化定义好的长度以获得更好的性能
+ StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+ int handledPosition = 0;
+ int delimIndex;// 占位符所在位置
+ for (int argIndex = 0; argIndex < argArray.length; argIndex++) {
+ delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+ if (delimIndex == -1) {
+ if (handledPosition == 0) {
+ return strPattern;
+ } else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+ sbuf.append(strPattern, handledPosition, strPatternLength);
+ return sbuf.toString();
+ }
+ } else {
+ if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) {
+ if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) {
+ // 转义符之前还有一个转义符,占位符依旧有效
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ } else {
+ // 占位符被转义
+ argIndex--;
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(C_DELIM_START);
+ handledPosition = delimIndex + 1;
+ }
+ } else {
+ // 正常占位符
+ sbuf.append(strPattern, handledPosition, delimIndex);
+ sbuf.append(utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ }
+ }
+ // 加入最后一个占位符后所有的字符
+ sbuf.append(strPattern, handledPosition, strPattern.length());
+
+ return sbuf.toString();
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @return 字符串
+ */
+ public static String utf8Str(Object obj) {
+ return str(obj, CHARSET_UTF_8);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charset 字符集
+ * @return 字符串
+ */
+ public static String str(Object obj, Charset charset) {
+ if (null == obj) {
+ return null;
+ }
+
+ if (obj instanceof String) {
+ return (String) obj;
+ } else if (obj instanceof byte[]) {
+ return str((byte[]) obj, charset);
+ } else if (obj instanceof Byte[]) {
+ byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
+ return str(bytes, charset);
+ } else if (obj instanceof ByteBuffer) {
+ return str((ByteBuffer) obj, charset);
+ }
+ return obj.toString();
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenUtils.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenUtils.java"
new file mode 100644
index 0000000..1a3bb69
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenUtils.java"
@@ -0,0 +1,249 @@
+package org.yang.crudplus.common.utils;
+
+
+
+import org.apache.commons.lang3.RegExUtils;
+import org.yang.crudplus.common.config.GenConfig;
+import org.yang.crudplus.common.constant.GenConstants;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.util.Arrays;
+
+/**
+ * 代码生成器 工具类
+ *
+ * @author ruoyi
+ */
+public class GenUtils
+{
+ /**
+ * 初始化表信息
+ */
+ public static void initTable(GenTable genTable)
+ {
+ genTable.setClassName(convertClassName(genTable.getTableName()));
+ genTable.setPackageName(GenConfig.getPackageName());
+ genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
+ genTable.setBusinessName(getBusinessName(genTable.getTableName()));
+ genTable.setFunctionName(genTable.getTableComment());
+ genTable.setFunctionAuthor(GenConfig.getAuthor());
+
+ }
+
+ /**
+ * 初始化列属性字段
+ */
+ public static void initColumnField(GenTableColumn column, GenTable table)
+ {
+ String dataType = getDbType(column.getColumnType());
+ String columnName = column.getColumnName();
+ column.setTableId(table.getTableId());
+ column.setCreateBy(table.getCreateBy());
+ // 设置java字段名
+ column.setJavaField(StringUtils.toCamelCase(columnName));
+ // 设置默认类型
+ column.setJavaType(GenConstants.TYPE_STRING);
+ column.setQueryType(GenConstants.QUERY_EQ);
+
+ if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
+ {
+ // 字符串长度超过500设置为文本域
+ Integer columnLength = getColumnLength(column.getColumnType());
+ String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
+ column.setHtmlType(htmlType);
+ }
+ else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
+ {
+ column.setJavaType(GenConstants.TYPE_DATE);
+ column.setHtmlType(GenConstants.HTML_DATETIME);
+ }
+ else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
+ {
+ column.setHtmlType(GenConstants.HTML_INPUT);
+
+ // 如果是浮点型 统一用BigDecimal
+ String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
+ if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
+ {
+ column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
+ }
+ // 如果是整形
+ else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
+ {
+ column.setJavaType(GenConstants.TYPE_INTEGER);
+ }
+ // 长整形
+ else
+ {
+ column.setJavaType(GenConstants.TYPE_LONG);
+ }
+ }
+
+ // 插入字段(默认所有字段都需要插入)
+ column.setIsInsert(GenConstants.REQUIRE);
+
+ // 编辑字段
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
+ {
+ column.setIsEdit(GenConstants.REQUIRE);
+ }
+ // 列表字段
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
+ {
+ column.setIsList(GenConstants.REQUIRE);
+ }
+ // 查询字段
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
+ {
+ column.setIsQuery(GenConstants.REQUIRE);
+ }
+
+ // 查询字段类型
+ if (StringUtils.endsWithIgnoreCase(columnName, "name"))
+ {
+ column.setQueryType(GenConstants.QUERY_LIKE);
+ }
+ // 状态字段设置单选框
+ if (StringUtils.endsWithIgnoreCase(columnName, "status"))
+ {
+ column.setHtmlType(GenConstants.HTML_RADIO);
+ }
+ // 类型&性别字段设置下拉框
+ else if (StringUtils.endsWithIgnoreCase(columnName, "type")
+ || StringUtils.endsWithIgnoreCase(columnName, "sex"))
+ {
+ column.setHtmlType(GenConstants.HTML_SELECT);
+ }
+ // 图片字段设置图片上传控件
+ else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
+ {
+ column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
+ }
+ // 文件字段设置文件上传控件
+ else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
+ {
+ column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
+ }
+ // 内容字段设置富文本控件
+ else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
+ {
+ column.setHtmlType(GenConstants.HTML_EDITOR);
+ }
+ }
+
+ /**
+ * 校验数组是否包含指定值
+ *
+ * @param arr 数组
+ * @param targetValue 值
+ * @return 是否包含
+ */
+ public static boolean arraysContains(String[] arr, String targetValue)
+ {
+ return Arrays.asList(arr).contains(targetValue);
+ }
+
+ /**
+ * 获取模块名
+ *
+ * @param packageName 包名
+ * @return 模块名
+ */
+ public static String getModuleName(String packageName)
+ {
+ int lastIndex = packageName.lastIndexOf(".");
+ int nameLength = packageName.length();
+ return StringUtils.substring(packageName, lastIndex + 1, nameLength);
+ }
+
+ /**
+ * 获取业务名
+ *
+ * @param tableName 表名
+ * @return 业务名
+ */
+ public static String getBusinessName(String tableName)
+ {
+ int lastIndex = tableName.lastIndexOf("_");
+ int nameLength = tableName.length();
+ return StringUtils.substring(tableName, lastIndex + 1, nameLength);
+ }
+
+ /**
+ * 表名转换成Java类名
+ *
+ * @param tableName 表名称
+ * @return 类名
+ */
+ public static String convertClassName(String tableName)
+ {
+ boolean autoRemovePre = GenConfig.getAutoRemovePre();
+ String tablePrefix = GenConfig.getTablePrefix();
+ if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix))
+ {
+ String[] searchList = StringUtils.split(tablePrefix, ",");
+ tableName = replaceFirst(tableName, searchList);
+ }
+ return StringUtils.convertToCamelCase(tableName);
+ }
+
+ /**
+ * 批量替换前缀
+ *
+ * @param replacementm 替换值
+ * @param searchList 替换列表
+ * @return
+ */
+ public static String replaceFirst(String replacementm, String[] searchList)
+ {
+ String text = replacementm;
+ for (String searchString : searchList)
+ {
+ if (replacementm.startsWith(searchString))
+ {
+ text = replacementm.replaceFirst(searchString, "");
+ break;
+ }
+ }
+ return text;
+ }
+
+
+ /**
+ * 获取数据库类型字段
+ *
+ * @param columnType 列类型
+ * @return 截取后的列类型
+ */
+ public static String getDbType(String columnType)
+ {
+ if (StringUtils.indexOf(columnType, "(") > 0)
+ {
+ return StringUtils.substringBefore(columnType, "(");
+ }
+ else
+ {
+ return columnType;
+ }
+ }
+
+ /**
+ * 获取字段长度
+ *
+ * @param columnType 列类型
+ * @return 截取后的列类型
+ */
+ public static Integer getColumnLength(String columnType)
+ {
+ if (StringUtils.indexOf(columnType, "(") > 0)
+ {
+ String length = StringUtils.substringBetween(columnType, "(", ")");
+ return Integer.valueOf(length);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenericConverter.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenericConverter.java"
new file mode 100644
index 0000000..59b0bd9
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/GenericConverter.java"
@@ -0,0 +1,55 @@
+package org.yang.crudplus.common.utils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GenericConverter {
+
+ private static final Map FIELD_CACHE = new HashMap<>();
+
+ public static R convert(T source, Class targetClass) {
+ if (source == null) {
+ return null;
+ }
+
+ try {
+ R target = targetClass.getDeclaredConstructor().newInstance();
+ Field[] sourceFields = getFields(source.getClass());
+ Field[] targetFields = getFields(targetClass);
+
+ for (Field sourceField : sourceFields) {
+ sourceField.setAccessible(true);
+ String fieldName = sourceField.getName();
+
+ for (Field targetField : targetFields) {
+ targetField.setAccessible(true);
+ if (targetField.getName().equals(fieldName)) {
+ Object value = sourceField.get(source);
+ if (value != null && !sourceField.getType().equals(targetField.getType())) {
+ value = convert(value, targetField.getType());
+ }
+ targetField.set(target, value);
+ break;
+ }
+ }
+ }
+ return target;
+ } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static Field[] getFields(Class> clazz) {
+ String key = clazz.getName();
+ if (FIELD_CACHE.containsKey(key)) {
+ return FIELD_CACHE.get(key);
+ }
+
+ Field[] fields = clazz.getDeclaredFields();
+ FIELD_CACHE.put(key, fields);
+ return fields;
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/StringUtils.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/StringUtils.java"
new file mode 100644
index 0000000..51f7218
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/StringUtils.java"
@@ -0,0 +1,670 @@
+package org.yang.crudplus.common.utils;
+
+
+import org.springframework.util.AntPathMatcher;
+import org.yang.crudplus.common.text.StrFormatter;
+
+import java.util.*;
+
+/**
+ * 字符串工具类
+ *
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+ /** 空字符串 */
+ private static final String NULLSTR = "";
+
+ /** 下划线 */
+ private static final char SEPARATOR = '_';
+
+ /** 星号 */
+ private static final char ASTERISK = '*';
+
+ /**
+ * 获取参数不为空值
+ *
+ * @param value defaultValue 要判断的value
+ * @return value 返回值
+ */
+ public static T nvl(T value, T defaultValue)
+ {
+ return value != null ? value : defaultValue;
+ }
+
+ /**
+ * * 判断一个Collection是否为空, 包含List,Set,Queue
+ *
+ * @param coll 要判断的Collection
+ * @return true:为空 false:非空
+ */
+ public static boolean isEmpty(Collection> coll)
+ {
+ return isNull(coll) || coll.isEmpty();
+ }
+
+ /**
+ * * 判断一个Collection是否非空,包含List,Set,Queue
+ *
+ * @param coll 要判断的Collection
+ * @return true:非空 false:空
+ */
+ public static boolean isNotEmpty(Collection> coll)
+ {
+ return !isEmpty(coll);
+ }
+
+ /**
+ * * 判断一个对象数组是否为空
+ *
+ * @param objects 要判断的对象数组
+ ** @return true:为空 false:非空
+ */
+ public static boolean isEmpty(Object[] objects)
+ {
+ return isNull(objects) || (objects.length == 0);
+ }
+
+ /**
+ * * 判断一个对象数组是否非空
+ *
+ * @param objects 要判断的对象数组
+ * @return true:非空 false:空
+ */
+ public static boolean isNotEmpty(Object[] objects)
+ {
+ return !isEmpty(objects);
+ }
+
+ /**
+ * * 判断一个Map是否为空
+ *
+ * @param map 要判断的Map
+ * @return true:为空 false:非空
+ */
+ public static boolean isEmpty(Map, ?> map)
+ {
+ return isNull(map) || map.isEmpty();
+ }
+
+ /**
+ * * 判断一个Map是否为空
+ *
+ * @param map 要判断的Map
+ * @return true:非空 false:空
+ */
+ public static boolean isNotEmpty(Map, ?> map)
+ {
+ return !isEmpty(map);
+ }
+
+ /**
+ * * 判断一个字符串是否为空串
+ *
+ * @param str String
+ * @return true:为空 false:非空
+ */
+ public static boolean isEmpty(String str)
+ {
+ return isNull(str) || NULLSTR.equals(str.trim());
+ }
+
+ /**
+ * * 判断一个字符串是否为非空串
+ *
+ * @param str String
+ * @return true:非空串 false:空串
+ */
+ public static boolean isNotEmpty(String str)
+ {
+ return !isEmpty(str);
+ }
+
+ /**
+ * * 判断一个对象是否为空
+ *
+ * @param object Object
+ * @return true:为空 false:非空
+ */
+ public static boolean isNull(Object object)
+ {
+ return object == null;
+ }
+
+ /**
+ * * 判断一个对象是否非空
+ *
+ * @param object Object
+ * @return true:非空 false:空
+ */
+ public static boolean isNotNull(Object object)
+ {
+ return !isNull(object);
+ }
+
+ /**
+ * * 判断一个对象是否是数组类型(Java基本型别的数组)
+ *
+ * @param object 对象
+ * @return true:是数组 false:不是数组
+ */
+ public static boolean isArray(Object object)
+ {
+ return isNotNull(object) && object.getClass().isArray();
+ }
+
+ /**
+ * 去空格
+ */
+ public static String trim(String str)
+ {
+ return (str == null ? "" : str.trim());
+ }
+
+ /**
+ * 替换指定字符串的指定区间内字符为"*"
+ *
+ * @param str 字符串
+ * @param startInclude 开始位置(包含)
+ * @param endExclude 结束位置(不包含)
+ * @return 替换后的字符串
+ */
+ public static String hide(CharSequence str, int startInclude, int endExclude)
+ {
+ if (isEmpty(str))
+ {
+ return NULLSTR;
+ }
+ final int strLength = str.length();
+ if (startInclude > strLength)
+ {
+ return NULLSTR;
+ }
+ if (endExclude > strLength)
+ {
+ endExclude = strLength;
+ }
+ if (startInclude > endExclude)
+ {
+ // 如果起始位置大于结束位置,不替换
+ return NULLSTR;
+ }
+ final char[] chars = new char[strLength];
+ for (int i = 0; i < strLength; i++)
+ {
+ if (i >= startInclude && i < endExclude)
+ {
+ chars[i] = ASTERISK;
+ }
+ else
+ {
+ chars[i] = str.charAt(i);
+ }
+ }
+ return new String(chars);
+ }
+
+ /**
+ * 截取字符串
+ *
+ * @param str 字符串
+ * @param start 开始
+ * @return 结果
+ */
+ public static String substring(final String str, int start)
+ {
+ if (str == null)
+ {
+ return NULLSTR;
+ }
+
+ if (start < 0)
+ {
+ start = str.length() + start;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+ if (start > str.length())
+ {
+ return NULLSTR;
+ }
+
+ return str.substring(start);
+ }
+
+ /**
+ * 截取字符串
+ *
+ * @param str 字符串
+ * @param start 开始
+ * @param end 结束
+ * @return 结果
+ */
+ public static String substring(final String str, int start, int end)
+ {
+ if (str == null)
+ {
+ return NULLSTR;
+ }
+
+ if (end < 0)
+ {
+ end = str.length() + end;
+ }
+ if (start < 0)
+ {
+ start = str.length() + start;
+ }
+
+ if (end > str.length())
+ {
+ end = str.length();
+ }
+
+ if (start > end)
+ {
+ return NULLSTR;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+ if (end < 0)
+ {
+ end = 0;
+ }
+
+ return str.substring(start, end);
+ }
+
+ /**
+ * 判断是否为空,并且不是空白字符
+ *
+ * @param str 要判断的value
+ * @return 结果
+ */
+ public static boolean hasText(String str)
+ {
+ return (str != null && !str.isEmpty() && containsText(str));
+ }
+
+ private static boolean containsText(CharSequence str)
+ {
+ int strLen = str.length();
+ for (int i = 0; i < strLen; i++)
+ {
+ if (!Character.isWhitespace(str.charAt(i)))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ *
+ * @param template 文本模板,被替换的部分用 {} 表示
+ * @param params 参数值
+ * @return 格式化后的文本
+ */
+ public static String format(String template, Object... params)
+ {
+ if (isEmpty(params) || isEmpty(template))
+ {
+ return template;
+ }
+ return StrFormatter.format(template, params);
+ }
+
+
+ /**
+ * 字符串转set
+ *
+ * @param str 字符串
+ * @param sep 分隔符
+ * @return set集合
+ */
+ public static final Set str2Set(String str, String sep)
+ {
+ return new HashSet(str2List(str, sep, true, false));
+ }
+
+ /**
+ * 字符串转list
+ *
+ * @param str 字符串
+ * @param sep 分隔符
+ * @param filterBlank 过滤纯空白
+ * @param trim 去掉首尾空白
+ * @return list集合
+ */
+ public static final List str2List(String str, String sep, boolean filterBlank, boolean trim)
+ {
+ List list = new ArrayList();
+ if (StringUtils.isEmpty(str))
+ {
+ return list;
+ }
+
+ // 过滤空白字符串
+ if (filterBlank && StringUtils.isBlank(str))
+ {
+ return list;
+ }
+ String[] split = str.split(sep);
+ for (String string : split)
+ {
+ if (filterBlank && StringUtils.isBlank(string))
+ {
+ continue;
+ }
+ if (trim)
+ {
+ string = string.trim();
+ }
+ list.add(string);
+ }
+
+ return list;
+ }
+
+ /**
+ * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+ *
+ * @param collection 给定的集合
+ * @param array 给定的数组
+ * @return boolean 结果
+ */
+ public static boolean containsAny(Collection collection, String... array)
+ {
+ if (isEmpty(collection) || isEmpty(array))
+ {
+ return false;
+ }
+ else
+ {
+ for (String str : array)
+ {
+ if (collection.contains(str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
+ *
+ * @param cs 指定字符串
+ * @param searchCharSequences 需要检查的字符串数组
+ * @return 是否包含任意一个字符串
+ */
+ public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+ {
+ if (isEmpty(cs) || isEmpty(searchCharSequences))
+ {
+ return false;
+ }
+ for (CharSequence testStr : searchCharSequences)
+ {
+ if (containsIgnoreCase(cs, testStr))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 驼峰转下划线命名
+ */
+ public static String toUnderScoreCase(String str)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ // 前置字符是否大写
+ boolean preCharIsUpperCase = true;
+ // 当前字符是否大写
+ boolean curreCharIsUpperCase = true;
+ // 下一字符是否大写
+ boolean nexteCharIsUpperCase = true;
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (i > 0)
+ {
+ preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+ }
+ else
+ {
+ preCharIsUpperCase = false;
+ }
+
+ curreCharIsUpperCase = Character.isUpperCase(c);
+
+ if (i < (str.length() - 1))
+ {
+ nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+ }
+
+ if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+ {
+ sb.append(SEPARATOR);
+ }
+ else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+ {
+ sb.append(SEPARATOR);
+ }
+ sb.append(Character.toLowerCase(c));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 是否包含字符串
+ *
+ * @param str 验证字符串
+ * @param strs 字符串组
+ * @return 包含返回true
+ */
+ public static boolean inStringIgnoreCase(String str, String... strs)
+ {
+ if (str != null && strs != null)
+ {
+ for (String s : strs)
+ {
+ if (str.equalsIgnoreCase(trim(s)))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+ *
+ * @param name 转换前的下划线大写方式命名的字符串
+ * @return 转换后的驼峰式命名的字符串
+ */
+ public static String convertToCamelCase(String name)
+ {
+ StringBuilder result = new StringBuilder();
+ // 快速检查
+ if (name == null || name.isEmpty())
+ {
+ // 没必要转换
+ return "";
+ }
+ else if (!name.contains("_"))
+ {
+ // 不含下划线,仅将首字母大写
+ return name.substring(0, 1).toUpperCase() + name.substring(1);
+ }
+ // 用下划线将原始字符串分割
+ String[] camels = name.split("_");
+ for (String camel : camels)
+ {
+ // 跳过原始字符串中开头、结尾的下换线或双重下划线
+ if (camel.isEmpty())
+ {
+ continue;
+ }
+ // 首字母大写
+ result.append(camel.substring(0, 1).toUpperCase());
+ result.append(camel.substring(1).toLowerCase());
+ }
+ return result.toString();
+ }
+
+ /**
+ * 驼峰式命名法
+ * 例如:user_name->userName
+ */
+ public static String toCamelCase(String s)
+ {
+ if (s == null)
+ {
+ return null;
+ }
+ if (s.indexOf(SEPARATOR) == -1)
+ {
+ return s;
+ }
+ s = s.toLowerCase();
+ StringBuilder sb = new StringBuilder(s.length());
+ boolean upperCase = false;
+ for (int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+
+ if (c == SEPARATOR)
+ {
+ upperCase = true;
+ }
+ else if (upperCase)
+ {
+ sb.append(Character.toUpperCase(c));
+ upperCase = false;
+ }
+ else
+ {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+ *
+ * @param str 指定字符串
+ * @param strs 需要检查的字符串数组
+ * @return 是否匹配
+ */
+ public static boolean matches(String str, List strs)
+ {
+ if (isEmpty(str) || isEmpty(strs))
+ {
+ return false;
+ }
+ for (String pattern : strs)
+ {
+ if (isMatch(pattern, str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判断url是否与规则配置:
+ * ? 表示单个字符;
+ * * 表示一层路径内的任意字符串,不可跨层级;
+ * ** 表示任意层路径;
+ *
+ * @param pattern 匹配规则
+ * @param url 需要匹配的url
+ * @return
+ */
+ public static boolean isMatch(String pattern, String url)
+ {
+ AntPathMatcher matcher = new AntPathMatcher();
+ return matcher.match(pattern, url);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T cast(Object obj)
+ {
+ return (T) obj;
+ }
+
+ /**
+ * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+ *
+ * @param num 数字对象
+ * @param size 字符串指定长度
+ * @return 返回数字的字符串格式,该字符串为指定长度。
+ */
+ public static final String padl(final Number num, final int size)
+ {
+ return padl(num.toString(), size, '0');
+ }
+
+ /**
+ * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+ *
+ * @param s 原始字符串
+ * @param size 字符串指定长度
+ * @param c 用于补齐的字符
+ * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
+ */
+ public static final String padl(final String s, final int size, final char c)
+ {
+ final StringBuilder sb = new StringBuilder(size);
+ if (s != null)
+ {
+ final int len = s.length();
+ if (s.length() <= size)
+ {
+ for (int i = size - len; i > 0; i--)
+ {
+ sb.append(c);
+ }
+ sb.append(s);
+ }
+ else
+ {
+ return s.substring(len - size, len);
+ }
+ }
+ else
+ {
+ for (int i = size; i > 0; i--)
+ {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/TypeChecker.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/TypeChecker.java"
new file mode 100644
index 0000000..a69b80f
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/TypeChecker.java"
@@ -0,0 +1,54 @@
+package org.yang.crudplus.common.utils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class TypeChecker {
+
+ private static final Set COMMON_RETURN_TYPES = new HashSet<>();
+
+ static {
+ COMMON_RETURN_TYPES.add("void");
+ COMMON_RETURN_TYPES.add("int");
+ COMMON_RETURN_TYPES.add("long");
+ COMMON_RETURN_TYPES.add("float");
+ COMMON_RETURN_TYPES.add("double");
+ COMMON_RETURN_TYPES.add("boolean");
+ COMMON_RETURN_TYPES.add("char");
+ COMMON_RETURN_TYPES.add("byte");
+ COMMON_RETURN_TYPES.add("short");
+ COMMON_RETURN_TYPES.add("String");
+ COMMON_RETURN_TYPES.add("Integer");
+ COMMON_RETURN_TYPES.add("Long");
+ COMMON_RETURN_TYPES.add("Float");
+ COMMON_RETURN_TYPES.add("Double");
+ COMMON_RETURN_TYPES.add("Boolean");
+ COMMON_RETURN_TYPES.add("Character");
+ COMMON_RETURN_TYPES.add("Byte");
+ COMMON_RETURN_TYPES.add("Short");
+ }
+
+ public static boolean isCommonReturnType(String type) {
+ return COMMON_RETURN_TYPES.contains(type);
+ }
+
+ public static boolean isClass(String type) {
+ try {
+ Class.forName(type);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static String determineType(String type) {
+ if (isCommonReturnType(type)) {
+ return "Common Return Type";
+ } else if (isClass(type)) {
+ return "Class";
+ } else {
+ return "Unknown";
+ }
+ }
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityInitializer.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityInitializer.java"
new file mode 100644
index 0000000..7721352
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityInitializer.java"
@@ -0,0 +1,36 @@
+package org.yang.crudplus.common.utils;
+
+
+import org.apache.velocity.app.Velocity;
+import org.yang.crudplus.common.constant.GenConstants;
+
+import java.util.Properties;
+
+/**
+ * VelocityEngine工厂
+ *
+ * @author ruoyi
+ */
+public class VelocityInitializer
+{
+ /**
+ * 初始化vm方法
+ */
+ public static void initVelocity()
+ {
+ Properties p = new Properties();
+ try
+ {
+ // 加载classpath目录下的vm文件
+ p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+ // 定义字符集
+ p.setProperty(Velocity.INPUT_ENCODING, GenConstants.UTF_8);
+ // 初始化Velocity引擎,指定配置Properties
+ Velocity.init(p);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityUtils.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityUtils.java"
new file mode 100644
index 0000000..373faca
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/common/utils/VelocityUtils.java"
@@ -0,0 +1,366 @@
+package org.yang.crudplus.common.utils;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+
+import org.apache.velocity.VelocityContext;
+import org.yang.crudplus.common.constant.GenConstants;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.vo.GenTableCRUD;
+import org.yang.crudplus.pojo.vo.GenTableColumnbVo;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 模板处理工具类
+ *
+ * @author ruoyi
+ */
+public class VelocityUtils {
+ /**
+ * 项目空间路径
+ */
+ private static final String PROJECT_PATH = "main/java";
+
+ /**
+ * mybatis空间路径
+ */
+ private static final String MYBATIS_PATH = "main/resources/mapper";
+
+ /**
+ * 默认上级菜单,系统工具
+ */
+ private static final String DEFAULT_PARENT_MENU_ID = "3";
+
+ /**
+ * 设置模板变量信息
+ *
+ * @return 模板列表
+ */
+ public static VelocityContext prepareContext(GenTableCRUD genTable) {
+ String moduleName = genTable.getModuleName();
+ String businessName = genTable.getBusinessName();
+ String packageName = genTable.getPackageName();
+ String tplCategory = genTable.getTplCategory();
+ String functionName = genTable.getFunctionName();
+
+ VelocityContext velocityContext = new VelocityContext();
+ velocityContext.put("tplCategory", genTable.getTplCategory());
+ velocityContext.put("tableName", genTable.getTableName());
+ velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : genTable.getClassName());
+ velocityContext.put("ClassName", genTable.getClassName());
+ velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
+ velocityContext.put("moduleName", genTable.getModuleName());
+ velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
+ velocityContext.put("businessName", genTable.getBusinessName());
+ //获取当前类的package名
+ velocityContext.put("basePackage", getPackagePrefix(packageName));
+ velocityContext.put("packageName", packageName);
+ velocityContext.put("author", genTable.getFunctionAuthor());
+ velocityContext.put("datetime", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+ velocityContext.put("pkColumn", genTable.getPkColumn());
+ //需要导入包的集合
+ velocityContext.put("importList", getImportList(genTable));
+ //获取权限前缀
+ velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
+ velocityContext.put("columns", genTable.getColumns());
+ velocityContext.put("table", genTable);
+ velocityContext.put("dicts", getDicts(genTable));
+ velocityContext.put("tableFunction", genTable.getTableFunction());//自定义方法
+
+
+ setMenuVelocityContext(velocityContext, genTable);
+ if (GenConstants.TPL_TREE.equals(tplCategory)) {
+ setTreeVelocityContext(velocityContext, genTable);
+ }
+ if (GenConstants.TPL_SUB.equals(tplCategory)) {
+ setSubVelocityContext(velocityContext, genTable);
+ }
+ return velocityContext;
+ }
+
+ public static void setMenuVelocityContext(VelocityContext context, GenTableCRUD genTable) {
+ String options = genTable.getOptions();
+ JSONObject paramsObj = JSON.parseObject(options);
+ String parentMenuId = getParentMenuId(paramsObj);
+ context.put("parentMenuId", parentMenuId);
+ }
+
+ public static void setTreeVelocityContext(VelocityContext context, GenTableCRUD genTable) {
+ String options = genTable.getOptions();
+ JSONObject paramsObj = JSON.parseObject(options);
+ String treeCode = getTreecode(paramsObj);
+ String treeParentCode = getTreeParentCode(paramsObj);
+ String treeName = getTreeName(paramsObj);
+
+ context.put("treeCode", treeCode);
+ context.put("treeParentCode", treeParentCode);
+ context.put("treeName", treeName);
+ context.put("expandColumn", getExpandColumn(genTable));
+ if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
+ context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+ }
+ if (paramsObj.containsKey(GenConstants.TREE_NAME)) {
+ context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME));
+ }
+ }
+
+ public static void setSubVelocityContext(VelocityContext context, GenTableCRUD genTable) {
+ GenTableCRUD subTable = genTable.getSubTable();
+ String subTableName = genTable.getSubTableName();
+ String subTableFkName = genTable.getSubTableFkName();
+ String subClassName = genTable.getSubTable().getClassName();
+ String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName);
+
+ context.put("subTable", subTable);
+ context.put("subTableName", subTableName);
+ context.put("subTableFkName", subTableFkName);
+ context.put("subTableFkClassName", subTableFkClassName);
+ context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName));
+ context.put("subClassName", subClassName);
+ context.put("subclassName", StringUtils.uncapitalize(subClassName));
+ context.put("subImportList", getImportList(genTable.getSubTable()));
+ }
+
+ /**
+ * 获取模板信息
+ *
+ * @param tplCategory 生成的模板
+ * @param tplWebType 前端类型
+ * @return 模板列表
+ */
+ public static Map> getTemplateList(String tplCategory, String tplWebType) {
+ Map> templates = new HashMap<>();
+ // 只生成一次的模板
+ List singleTemplates = new ArrayList<>();
+ singleTemplates.add("vm/java/domain.java.vm");
+ singleTemplates.add("vm/java/mapper.java.vm");
+ singleTemplates.add("vm/java/controller.java.vm");
+ singleTemplates.add("vm/xml/mapper.xml.vm");
+
+ // 根据自定义方法生成的模板
+ List customTemplates = new ArrayList<>();
+ customTemplates.add("vm/java/req.java.vm");
+ customTemplates.add("vm/java/resp.java.vm");
+
+ List singleAndCustom = new ArrayList<>();
+ singleAndCustom.add("vm/java/service.java.vm");
+ singleAndCustom.add("vm/java/serviceImpl.java.vm");
+
+ templates.put("single", singleTemplates);
+ templates.put("custom", customTemplates);
+ templates.put("singleAndCustom",singleAndCustom);
+
+ return templates;
+ }
+
+
+
+ /**
+ * 获取文件名
+ */
+ public static String getFileName(String template, GenTableCRUD genTable,String customPath) {
+ // 文件名称
+ String fileName = "";
+ // 包路径
+ String packageName = genTable.getPackageName();
+ // 模块名
+ String moduleName = genTable.getModuleName();
+ // 大写类名
+ String className = genTable.getClassName();
+ // 业务名称
+ String businessName = genTable.getBusinessName();
+
+ String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
+ String mybatisPath = MYBATIS_PATH + "/" + moduleName;
+ String vuePath = "vue";
+
+ if (template.contains("domain.java.vm")) {
+ fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
+ }
+ if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory())) {
+ fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
+ } else if (template.contains("mapper.java.vm")) {
+ fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
+ } else if (template.contains("service.java.vm")) {
+ fileName = StringUtils.format("{}/service/{}Service.java", javaPath, className);
+ } else if (template.contains("serviceImpl.java.vm")) {
+ fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
+ } else if (template.contains("controller.java.vm")) {
+ fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
+ } else if (template.contains("mapper.xml.vm")) {
+ fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
+ } else if (template.contains("sql.vm")) {
+ fileName = businessName + "Menu.sql";
+ } else if (template.contains("api.js.vm")) {
+ fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
+ } else if (template.contains("index.vue.vm")) {
+ fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+ } else if (template.contains("index-tree.vue.vm")) {
+ fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+ } else if (template.contains("req.java.vm")) {
+ fileName=StringUtils.format("{}/domain/req/{}.java", javaPath, customPath);
+ } else if (template.contains("resp.java.vm")) {
+ fileName=StringUtils.format("{}/domain/resp/{}.java", javaPath, customPath);
+ }
+ return fileName;
+ }
+
+ /**
+ * 获取包前缀
+ *
+ * @param packageName 包名称
+ * @return 包前缀名称
+ */
+ public static String getPackagePrefix(String packageName) {
+ int lastIndex = packageName.lastIndexOf(".");
+ return StringUtils.substring(packageName, 0, lastIndex);
+ }
+
+ /**
+ * 根据列类型获取导入包
+ *
+ * @param genTable 业务表对象
+ * @return 返回需要导入的包列表
+ */
+ public static HashSet getImportList(GenTableCRUD genTable) {
+ List columns = genTable.getColumns();
+ GenTableCRUD subTable = genTable.getSubTable();
+ HashSet importList = new HashSet();
+ if (StringUtils.isNotNull(subTable)) {
+ importList.add("java.util.List");
+ }
+ for (GenTableColumn column : columns) {
+ if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) {
+ importList.add("java.util.Date");
+ importList.add("com.fasterxml.jackson.annotation.JsonFormat");
+ } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) {
+ importList.add("java.math.BigDecimal");
+ }
+ }
+ return importList;
+ }
+
+ /**
+ * 根据列类型获取字典组
+ *
+ * @param genTable 业务表对象
+ * @return 返回字典组
+ */
+ public static String getDicts(GenTableCRUD genTable) {
+ List columns = genTable.getColumns();
+ Set dicts = new HashSet();
+ addDicts(dicts, columns);
+ //主子表
+ if (StringUtils.isNotNull(genTable.getSubTable())) {
+ List subColumns = genTable.getSubTable().getColumns();
+ addDicts(dicts, subColumns);
+ }
+ return StringUtils.join(dicts, ", ");
+ }
+
+ /**
+ * 添加字典列表
+ *
+ * @param dicts 字典列表
+ * @param columns 列集合
+ */
+ public static void addDicts(Set dicts, List columns) {
+ for (GenTableColumn column : columns) {
+ if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
+ column.getHtmlType(),
+ new String[]{GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX})) {
+ dicts.add("'" + column.getDictType() + "'");
+ }
+ }
+ }
+
+ /**
+ * 获取权限前缀
+ *
+ * @param moduleName 模块名称
+ * @param businessName 业务名称
+ * @return 返回权限前缀
+ */
+ public static String getPermissionPrefix(String moduleName, String businessName) {
+ return StringUtils.format("{}:{}", moduleName, businessName);
+ }
+
+ /**
+ * 获取上级菜单ID字段
+ *
+ * @param paramsObj 生成其他选项
+ * @return 上级菜单ID字段
+ */
+ public static String getParentMenuId(JSONObject paramsObj) {
+ if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
+ && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID))) {
+ return paramsObj.getString(GenConstants.PARENT_MENU_ID);
+ }
+ return DEFAULT_PARENT_MENU_ID;
+ }
+
+ /**
+ * 获取树编码
+ *
+ * @param paramsObj 生成其他选项
+ * @return 树编码
+ */
+ public static String getTreecode(JSONObject paramsObj) {
+ if (paramsObj.containsKey(GenConstants.TREE_CODE)) {
+ return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 获取树父编码
+ *
+ * @param paramsObj 生成其他选项
+ * @return 树父编码
+ */
+ public static String getTreeParentCode(JSONObject paramsObj) {
+ if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
+ return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 获取树名称
+ *
+ * @param paramsObj 生成其他选项
+ * @return 树名称
+ */
+ public static String getTreeName(JSONObject paramsObj) {
+ if (paramsObj.containsKey(GenConstants.TREE_NAME)) {
+ return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 获取需要在哪一列上面显示展开按钮
+ *
+ * @param genTable 业务表对象
+ * @return 展开按钮列序号
+ */
+ public static int getExpandColumn(GenTableCRUD genTable) {
+ String options = genTable.getOptions();
+ JSONObject paramsObj = JSON.parseObject(options);
+ String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+ int num = 0;
+ for (GenTableColumn column : genTable.getColumns()) {
+ if (column.isList()) {
+ num++;
+ String columnName = column.getColumnName();
+ if (columnName.equals(treeName)) {
+ break;
+ }
+ }
+ }
+ return num;
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableContrller.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableContrller.java"
new file mode 100644
index 0000000..e386c3d
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableContrller.java"
@@ -0,0 +1,180 @@
+package org.yang.crudplus.controller;
+
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.yang.crudplus.common.exception.CustomException;
+import org.yang.crudplus.common.utils.StringUtils;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.req.GenTableReq;
+import org.yang.crudplus.pojo.req.GenTableSaveReq;
+import org.yang.crudplus.pojo.resp.GenTableListResp;
+import org.yang.crudplus.pojo.resp.GenTablesUpdateResp;
+import org.yang.crudplus.pojo.resp.Response;
+import org.yang.crudplus.service.GenTableService;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/table")
+@Validated
+public class TableContrller {
+
+ @Autowired
+ private GenTableService genTableService;
+
+ /**
+ * 查询导入的表格列表
+ *
+ * @param req
+ * @return
+ */
+ @GetMapping("/list")
+ public Response list(@Valid GenTableReq req) {
+ log.info("表格数据集合请求:{}", req.toString());
+ GenTableListResp resp = genTableService.list(req);
+ log.info("表格数据请求响应:{}", resp);
+ return new Response<>(resp);
+ }
+
+ /**
+ * 系统表格查询
+ *
+ * @param req
+ * @return
+ */
+ @GetMapping("/db/list")
+ public Response> DBlist(@Valid GenTableReq req) {
+ log.info("系统表格查询请求:{}", req.toString());
+ List resp = genTableService.DBlist(req);
+ log.info("系统表格查询响应:{}", resp);
+ return new Response<>(resp);
+ }
+
+ /**
+ * 导入表结构
+ *
+ * @param tables
+ * @return
+ */
+ @PostMapping("/importTable")
+ public Response importTable(@RequestBody String[] tables) {
+ log.info("导入表结构请求:{}", Arrays.toString(tables));
+ if (tables == null || tables.length == 0) {
+ return new Response<>(400, "参数为空");
+ }
+ genTableService.importTable(tables);
+ return new Response<>(200, "导入成功");
+ }
+
+ /**
+ * 查询代码生成配置信息
+ *
+ * @param tableId
+ * @return
+ */
+ @GetMapping("/{tableId}")
+ public Response getTableInfo(@PathVariable("tableId") Long tableId) {
+ log.info("查询表格详情请求:{}", tableId);
+ GenTablesUpdateResp resp = genTableService.getTableInfo(tableId);
+ log.info("查询表格详情响应:{}", resp);
+ return new Response<>(resp);
+ }
+
+ /**
+ * 删除代码生成
+ *
+ * @param tableIds
+ * @return
+ */
+ @PostMapping("/delete")
+ public Response deleteTable(@RequestBody String[] tableIds) {
+ log.info("删除表格请求:{}", Arrays.toString(tableIds));
+ genTableService.removeById(tableIds);
+ return new Response<>();
+ }
+ /**
+ * 同步表结构:等同于重新导入
+ * 丢失相关信息
+ *
+ * @param tableName
+ * @return
+ */
+ @GetMapping("/synchDb/{tableName}")
+ public Response synchDb (@PathVariable("tableName") String tableName){
+ log.info("同步表结构请求:{}", tableName);
+ genTableService.synchDb(tableName);
+ return new Response<>();
+ }
+
+ /**
+ * 保存表配置信息请求
+ *
+ * @param req
+ * @return
+ */
+ @PostMapping("/save")
+ public Response save (@RequestBody GenTableSaveReq req){
+ log.info("保存表配置信息请求:{}", req.toString());
+ genTableService.saveConfig(req);
+ return new Response<>();
+ }
+
+ /**
+ * 代码生成--单表crud
+ *
+ * @param response
+ * @param tables
+ * @throws IOException
+ */
+ @GetMapping("/batchGenCode")
+ public Response batchGenCode (HttpServletResponse response, String tables) throws IOException {
+ log.info("批量生成代码请求:{}", tables.toString());
+ if (StringUtils.isBlank(tables)) {
+ throw new CustomException(400, "参数为空");
+ }
+ String[] tableNames = StringUtils.split(tables, ",");
+ byte[] data = genTableService.downloadCode(tableNames);
+ genCode(response, data);
+ return new Response<>();
+ }
+
+
+ /**
+ * 生成zip文件
+ */
+ private void genCode (HttpServletResponse response,byte[] data) throws IOException {
+ response.reset();
+ response.addHeader("Access-Control-Allow-Origin", "*");
+ response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
+ response.setHeader("Content-Disposition", "attachment; filename=\"crud.zip\"");
+ response.addHeader("Content-Length", "" + data.length);
+ response.setContentType("application/octet-stream; charset=UTF-8");
+ IOUtils.write(data, response.getOutputStream());
+ }
+
+ /**
+ * 跟据表名称,查询字段集合
+ *
+ * @param tableName
+ * @return
+ */
+ @GetMapping("/getTableColumns")
+ public Response> getTableColumnListByTableName (String tableName){
+ log.info("根据表名称查询字段集合请求:{}", tableName);
+ List resp = genTableService.getTableColumnListByTableName(tableName);
+ log.info("根据表名称查询字段集合响应:{}", resp);
+ return new Response<>(resp);
+ }
+
+
+ }
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableFunctionController.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableFunctionController.java"
new file mode 100644
index 0000000..09ca3e0
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/controller/TableFunctionController.java"
@@ -0,0 +1,145 @@
+package org.yang.crudplus.controller;
+
+import java.io.IOException;
+import java.util.List;
+
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import org.yang.crudplus.common.exception.CustomException;
+import org.yang.crudplus.common.utils.StringUtils;
+import org.yang.crudplus.pojo.TableFunction;
+import org.yang.crudplus.pojo.req.TableFunctionListReq;
+import org.yang.crudplus.pojo.req.TableFunnctionSaveReq;
+import org.yang.crudplus.pojo.resp.CustomReqRespList;
+import org.yang.crudplus.pojo.resp.Response;
+import org.yang.crudplus.pojo.resp.TableFunctionListResp;
+import org.yang.crudplus.pojo.resp.TableFunnctionSaveResp;
+import org.yang.crudplus.service.ITableFunctionService;
+
+
+/**
+ * TableFunctionController
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+@Slf4j
+@RestController
+@RequestMapping("/plus/table")
+public class TableFunctionController {
+ @Autowired
+ private ITableFunctionService tableFunctionService;
+
+ /**
+ * 保存crud的方法
+ *
+ * @return
+ */
+ @PostMapping("/save")
+ public Response add(@RequestBody TableFunnctionSaveReq req) {
+ log.info("保存crud的方法请求:{}", req.toString());
+ tableFunctionService.saveConfig(req);
+ return new Response<>();
+ }
+
+
+ /**
+ * 代码生成--单表-service层自定义方法
+ *
+ * @param response
+ * @param tables
+ * @throws IOException
+ */
+ @GetMapping("/batchGenCode")
+ public Response batchGenCode(HttpServletResponse response, String tables) throws IOException {
+ log.info("代码生成--单表-service层自定义方法:{}", tables.toString());
+ if (StringUtils.isBlank(tables)) {
+ throw new CustomException(400, "参数为空");
+ }
+ String[] tableNames = StringUtils.split(tables, ",");
+ byte[] data = tableFunctionService.downloadCode(tableNames);
+ genCode(response, data);
+ return new Response<>();
+ }
+
+
+ /**
+ * 生成zip文件
+ */
+ private void genCode(HttpServletResponse response, byte[] data) throws IOException {
+ response.reset();
+ response.addHeader("Access-Control-Allow-Origin", "*");
+ response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
+ response.setHeader("Content-Disposition", "attachment; filename=\"crud.zip\"");
+ response.addHeader("Content-Length", "" + data.length);
+ response.setContentType("application/octet-stream; charset=UTF-8");
+ IOUtils.write(data, response.getOutputStream());
+ }
+
+ /**
+ * 查询tableFunction列表
+ *
+ * @param req
+ * @return
+ */
+ @GetMapping("/list")
+ public Response> list(TableFunctionListReq req) {
+ log.info("查询tableFunction列表请求:{}", req.toString());
+ Listresp = tableFunctionService.list(req);
+ log.info("查询tableFunction列表响应:{}", resp);
+ return new Response<>(resp);
+ }
+
+ /**
+ * 自定义的方法请求对象
+ */
+ @GetMapping("/customReqList")
+ public Response> customReqList() {
+ log.info("自定义的方法请求对象");
+ return new Response<>(tableFunctionService.customReResoList("req"));
+ }
+
+ /**
+ * 自定义的方法请求对象
+ */
+ @GetMapping("/customRespList")
+ public Response> customRespList() {
+ log.info("自定义的方法请求对象");
+ return new Response<>(tableFunctionService.customReResoList("resp"));
+ }
+
+ /**
+ * 跟据方法id获取到该方法的相关信息
+ * @param functionId
+ * @return
+ */
+ @GetMapping("/functionInfoById")
+ public Response functionInfoById(Long functionId) {
+ log.info("查询tableFunction列表请求:{}", functionId);
+ return new Response<>(tableFunctionService.functionInfoById(functionId));
+ }
+
+ /**
+ * 删除方法
+ * @param functionId
+ * @return
+ */
+ @GetMapping("/deleteById")
+ public Response deleteById(Long functionId){
+ log.info("删除请求:{}", functionId);
+ tableFunctionService.deleteFunctionById(functionId);
+ return new Response<>();
+ }
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableColumnMapper.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableColumnMapper.java"
new file mode 100644
index 0000000..c23fb0e
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableColumnMapper.java"
@@ -0,0 +1,61 @@
+package org.yang.crudplus.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.util.List;
+
+public interface GenTableColumnMapper extends BaseMapper {
+ /**
+ * 根据表名称查询列信息
+ *
+ * @param tableName 表名称
+ * @return 列信息
+ */
+
+ @Select("")
+ public List selectDbTableColumnsByName(@Param("tableName") String tableName);
+
+
+ /**
+ * 查询业务字段列表
+ *
+ * @param tableId 业务字段编号
+ * @return 业务字段集合
+ */
+
+ @Select(
+ " select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column " +
+ "where table_id = #{tableId} " +
+ " order by sort"
+ )
+ public List selectGenTableColumnListByTableId(@Param("tableId") Long tableId);
+
+
+ @Select("SELECT column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time FROM gen_table_column WHERE table_id = #{tableId} ORDER BY sort")
+ List selectByTableId(Long tableId);
+
+
+ @Select("")
+ List selectFunctionByTableName(@Param("type") String type, @Param("functionId") Long functionId);
+
+}
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableMapper.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableMapper.java"
new file mode 100644
index 0000000..7f77cd2
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/GenTableMapper.java"
@@ -0,0 +1,134 @@
+package org.yang.crudplus.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.*;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.req.GenTableReq;
+import org.yang.crudplus.pojo.vo.GenTableColumnbVo;
+
+import java.util.List;
+
+public interface GenTableMapper extends BaseMapper {
+
+
+ /**
+ * 查询数据库中有那些表
+ *
+ * @param req
+ * @return
+ */
+ @Select("")
+ public List DBlist(Page page, @Param("req") GenTableReq req);
+
+
+ /**
+ * 查询据库列表
+ *
+ * @param tableNames 表名称组
+ * @return 数据库表集合
+ */
+
+ @Select("")
+ public List selectDbTableListByNames(String[] tableNames);
+
+
+ /**
+ * 查询表ID业务信息
+ *
+ * @param tableId 业务ID
+ * @return 业务信息
+ */
+
+ @Select("SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, " +
+ "t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, " +
+ "t.gen_type, t.gen_path, t.options, t.remark, c.column_id, c.column_name, c.column_comment, c.column_type, " +
+ "c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, " +
+ "c.is_query, c.query_type, c.html_type, c.dict_type, c.sort FROM gen_table t LEFT JOIN gen_table_column c " +
+ " ON t.table_id = c.table_id WHERE t.table_id = #{tableId} ORDER BY c.sort")
+ @Results({
+ @Result(column = "table_id", property = "tableId"),
+ @Result(column = "table_name", property = "tableName"),
+ @Result(column = "table_comment", property = "tableComment"),
+ @Result(column = "sub_table_name", property = "subTableName"),
+ @Result(column = "sub_table_fk_name", property = "subTableFkName"),
+ @Result(column = "class_name", property = "className"),
+ @Result(column = "tpl_category", property = "tplCategory"),
+ @Result(column = "tpl_web_type", property = "tplWebType"),
+ @Result(column = "package_name", property = "packageName"),
+ @Result(column = "module_name", property = "moduleName"),
+ @Result(column = "business_name", property = "businessName"),
+ @Result(column = "function_name", property = "functionName"),
+ @Result(column = "function_author", property = "functionAuthor"),
+ @Result(column = "gen_type", property = "genType"),
+ @Result(column = "gen_path", property = "genPath"),
+ @Result(column = "options", property = "options"),
+ @Result(column = "remark", property = "remark"),
+ @Result(property = "columns", column = "table_id", javaType = List.class, many = @Many(select = "org.yang.crudplus.mapper.GenTableColumnMapper.selectByTableId"))
+ })
+ List selectGenTableById(Long tableId);
+
+ @Select("SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, " +
+ "t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, " +
+ "t.gen_type, t.gen_path, t.options, t.remark, c.column_id, c.column_name, c.column_comment, c.column_type, " +
+ "c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, " +
+ "c.is_query, c.query_type, c.html_type, c.dict_type, c.sort FROM gen_table t LEFT JOIN gen_table_column c " +
+ " ON t.table_id = c.table_id WHERE t.table_name = #{tableName} ORDER BY c.sort")
+ @Results({
+ @Result(column = "table_id", property = "tableId"),
+ @Result(column = "table_name", property = "tableName"),
+ @Result(column = "table_comment", property = "tableComment"),
+ @Result(column = "sub_table_name", property = "subTableName"),
+ @Result(column = "sub_table_fk_name", property = "subTableFkName"),
+ @Result(column = "class_name", property = "className"),
+ @Result(column = "tpl_category", property = "tplCategory"),
+ @Result(column = "tpl_web_type", property = "tplWebType"),
+ @Result(column = "package_name", property = "packageName"),
+ @Result(column = "module_name", property = "moduleName"),
+ @Result(column = "business_name", property = "businessName"),
+ @Result(column = "function_name", property = "functionName"),
+ @Result(column = "function_author", property = "functionAuthor"),
+ @Result(column = "gen_type", property = "genType"),
+ @Result(column = "gen_path", property = "genPath"),
+ @Result(column = "options", property = "options"),
+ @Result(column = "remark", property = "remark"),
+ @Result(property = "columns", column = "table_id", javaType = List.class, many = @Many(select = "org.yang.crudplus.mapper.GenTableColumnMapper.selectByTableId")) })
+ List selectGenTableByName(@Param("tableName") String tableName);
+
+
+ /**
+ * 查询所有表信息
+ *
+ * @return 表信息集合
+ */
+ @Select(
+ " SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark, " +
+ " c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort " +
+ " FROM gen_table t " +
+ " LEFT JOIN gen_table_column c ON t.table_id = c.table_id " +
+ " order by c.sort"
+ )
+ public List selectGenTableAll();
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionColumnMapper.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionColumnMapper.java"
new file mode 100644
index 0000000..b42b391
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionColumnMapper.java"
@@ -0,0 +1,10 @@
+package org.yang.crudplus.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.yang.crudplus.pojo.TableFunctionColumn;
+
+public interface TableFunctionColumnMapper extends BaseMapper {
+
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionMapper.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionMapper.java"
new file mode 100644
index 0000000..81e65dc
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/mapper/TableFunctionMapper.java"
@@ -0,0 +1,55 @@
+package org.yang.crudplus.mapper;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.TableFunction;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.yang.crudplus.pojo.resp.TableFunctionResp;
+
+
+/**
+ * TableFunction的Mapper接口
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+public interface TableFunctionMapper extends BaseMapper {
+
+ @Select("")
+ List selectListPage(Page page, @Param("tableName") String tableName);
+
+ @Select("")
+ List selectTableFunction(@Param("tableName") String tableName);
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTable.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTable.java"
new file mode 100644
index 0000000..4d6b303
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTable.java"
@@ -0,0 +1,108 @@
+package org.yang.crudplus.pojo;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 代码生成业务表
+ *
+ * @TableName gen_table
+ */
+@Data
+public class GenTable implements Serializable {
+
+ /**
+ * 编号
+ */
+ @TableId(type = IdType.AUTO)
+ private Long tableId;
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+
+ private String tableComment;
+ /**
+ * 关联子表的表名
+ */
+ private String subTableName;
+ /**
+ * 子表关联的外键名
+ */
+ private String subTableFkName;
+ /**
+ * 实体类名称
+ */
+ private String className;
+ /**
+ * 使用的模板(crud单表操作 tree树表操作)
+ */
+ private String tplCategory;
+ /**
+ * 前端模板类型(element-ui模版 element-plus模版)
+ */
+ private String tplWebType;
+ /**
+ * 生成包路径
+ */
+ private String packageName;
+ /**
+ * 生成模块名
+ */
+ private String moduleName;
+ /**
+ * 生成业务名
+ */
+ private String businessName;
+ /**
+ * 生成功能名
+ */
+ private String functionName;
+ /**
+ * 生成功能作者
+ */
+ private String functionAuthor;
+ /**
+ * 生成代码方式(0zip压缩包 1自定义路径)
+ */
+ private String genType;
+ /**
+ * 生成路径(不填默认项目路径)
+ */
+ private String genPath;
+ /**
+ * 其它生成选项
+ */
+ private String options;
+ /**
+ * 创建者
+ */
+ private String createBy;
+ /**
+ * 创建时间
+ */
+
+ private Date createTime;
+ /**
+ * 更新者
+ */
+ private String updateBy;
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+ /**
+ * 备注
+ */
+ private String remark;
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTableColumn.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTableColumn.java"
new file mode 100644
index 0000000..2425c05
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/GenTableColumn.java"
@@ -0,0 +1,156 @@
+package org.yang.crudplus.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+import org.yang.crudplus.common.utils.StringUtils;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 代码生成业务表字段
+ *
+ * @TableName gen_table_column
+ */
+@Data
+public class GenTableColumn implements Serializable {
+
+ /**
+ * 编号
+ */
+ @TableId(type = IdType.AUTO)
+ private Long columnId;
+ /**
+ * 归属表编号
+ */
+
+ private Long tableId;
+ /**
+ * 列名称
+ */
+ private String columnName;
+ /**
+ * 列描述
+ */
+ private String columnComment;
+ /**
+ * 列类型
+ */
+ private String columnType;
+ /**
+ * JAVA类型
+ */
+ private String javaType;
+ /**
+ * JAVA字段名
+ */
+ private String javaField;
+ /**
+ * 是否主键(1是)
+ */
+ private String isPk;
+ /**
+ * 是否自增(1是)
+ */
+ private String isIncrement;
+ /**
+ * 是否必填(1是)
+ */
+ private String isRequired;
+ /**
+ * 是否为插入字段(1是)
+ */
+ private String isInsert;
+ /**
+ * 是否编辑字段(1是)
+ */
+ private String isEdit;
+ /**
+ * 是否列表字段(1是)
+ */
+ private String isList;
+ /**
+ * 是否查询字段(1是)
+ */
+
+ private String isQuery;
+ /**
+ * 查询方式(等于、不等于、大于、小于、范围)
+ */
+ private String queryType;
+ /**
+ * 显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)
+ */
+ private String htmlType;
+ /**
+ * 字典类型
+ */
+ private String dictType;
+ /**
+ * 排序
+ */
+ private Integer sort;
+ /**
+ * 创建者
+ */
+ private String createBy;
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+ /**
+ * 更新者
+ */
+ private String updateBy;
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+ /**
+ * java字段名转首字母大写
+ */
+ @TableField(exist = false)
+ private String javaFieldStr;
+
+
+ public boolean isPk()
+ {
+ return isPk(this.isPk);
+ }
+
+ public boolean isPk(String isPk)
+ {
+ return isPk != null && StringUtils.equals("1", isPk);
+ }
+
+
+ public boolean isSuperColumn()
+ {
+ return isSuperColumn(this.javaField);
+ }
+
+ public static boolean isSuperColumn(String javaField)
+ {
+ return StringUtils.equalsAnyIgnoreCase(javaField,
+ // BaseEntity
+ "createBy", "createTime", "updateBy", "updateTime", "remark",
+ // TreeEntity
+ "parentName", "parentId", "orderNum", "ancestors");
+ }
+
+ public boolean isList()
+ {
+ return isList(this.isList);
+ }
+
+ public boolean isList(String isList)
+ {
+ return isList != null && StringUtils.equals("1", isList);
+ }
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunction.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunction.java"
new file mode 100644
index 0000000..02898b8
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunction.java"
@@ -0,0 +1,63 @@
+package org.yang.crudplus.pojo;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+/**
+ * table_function表的实体对象 tableFunction
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+@Data
+public class TableFunction {
+
+ /**
+ * 方法id
+ */
+ @TableId(type = IdType.AUTO)
+ private Long functionId;
+ /**
+ * 表id
+ */
+ private Long tableId;
+ /**
+ * 方法名称
+ */
+ private String functionName;
+ /**
+ * 方法描述
+ */
+ private String functionDescription;
+ /**
+ * 方法类型(insert,update,delete,selelct)
+ */
+ private String functionType;
+ /**
+ * 方法请求对象名称
+ */
+ private String functionReq;
+ /**
+ * 方法响应对象名称
+ */
+ private String functionResp;
+ /**
+ * 使用的方法响应对象名称
+ */
+ private String functionRespUse;
+ /**
+ * 使用方法的请求对象名称
+ */
+ private String functionReqUse;
+ /**
+ * 方法响应对象自定义名称
+ */
+ private String functionRespCustom;
+
+
+
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunctionColumn.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunctionColumn.java"
new file mode 100644
index 0000000..badc188
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/TableFunctionColumn.java"
@@ -0,0 +1,73 @@
+package org.yang.crudplus.pojo;
+
+
+import com.baomidou.mybatisplus.annotation.TableId;
+
+/**
+ * table_function_column表的实体对象 tableFunctionColumn
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+public class TableFunctionColumn {
+
+ /**
+ * 方法字段id
+ */
+ @TableId
+ private Long functionColumId;
+ /**
+ * 基类字段id
+ */
+ private Long columnId;
+ /**
+ * 方法id
+ */
+ private Long tableFunctionId;
+ /**
+ * 字段所属对象(req,resp)
+ */
+ private String functionColumType;
+
+ public void setFunctionColumId(Long functionColumId) {
+ this.functionColumId = functionColumId;
+ }
+
+ public Long getFunctionColumId() {
+ return functionColumId;
+ }
+
+ public void setColumnId(Long columnId) {
+ this.columnId = columnId;
+ }
+
+ public Long getColumnId() {
+ return columnId;
+ }
+
+ public void setTableFunctionId(Long tableFunctionId) {
+ this.tableFunctionId = tableFunctionId;
+ }
+
+ public Long getTableFunctionId() {
+ return tableFunctionId;
+ }
+
+ public void setFunctionColumType(String functionColumType) {
+ this.functionColumType = functionColumType;
+ }
+
+ public String getFunctionColumType() {
+ return functionColumType;
+ }
+
+ @Override
+ public String toString() {
+ return "TableFunctionColumn{"
+ + "functionColumId=" + getFunctionColumId()
+ + "columnId=" + getColumnId()
+ + "tableFunctionId=" + getTableFunctionId()
+ + "functionColumType=" + getFunctionColumType()
+ + "}";
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableReq.java"
new file mode 100644
index 0000000..130e9df
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableReq.java"
@@ -0,0 +1,33 @@
+package org.yang.crudplus.pojo.req;
+
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 代码生成表
+ *
+ * @TableName gen_table
+ */
+@Data
+public class GenTableReq implements Serializable {
+
+
+ /**
+ * 表名
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+ private String tableComment;
+ @NotNull(message = "PageNum cannot be null")
+ @Min(value = 1, message = "分页大小不低于1")
+ private int pageNum;
+ @NotNull(message = "PageSize cannot be null")
+ @Min(value = 1, message = "分页总数不低于1")
+ private int pageSize;
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableSaveReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableSaveReq.java"
new file mode 100644
index 0000000..2d351bb
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/GenTableSaveReq.java"
@@ -0,0 +1,53 @@
+package org.yang.crudplus.pojo.req;
+
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.io.Serializable;
+import java.util.List;
+/**
+ * 代码生成配置保存请求对象
+ */
+@Data
+public class GenTableSaveReq implements Serializable {
+ /**
+ * 表id
+ */
+ private Long tableId;
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+ private String tableComment;
+ /**
+ * 类名称
+ */
+ private String className;
+
+ /**
+ * 作者
+ */
+ private String functionAuthor;
+ /**
+ * 包路径
+ */
+ private String packageName;
+
+ /**
+ * 生成路径(不填默认项目路径)
+ */
+ private String genPath;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 字段生成信息
+ */
+ private List columns;
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunctionListReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunctionListReq.java"
new file mode 100644
index 0000000..0435294
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunctionListReq.java"
@@ -0,0 +1,24 @@
+package org.yang.crudplus.pojo.req;
+
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 自定义方法生成
+ */
+@Data
+public class TableFunctionListReq implements Serializable {
+ /**
+ * 使用的表名称
+ */
+ private String tableName;
+ @NotNull(message = "PageNum cannot be null")
+ @Min(value = 1, message = "分页大小不低于1")
+ private int pageNum;
+ @NotNull(message = "PageSize cannot be null")
+ @Min(value = 1, message = "分页总数不低于1")
+ private int pageSize;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunnctionSaveReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunnctionSaveReq.java"
new file mode 100644
index 0000000..7a2046e
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/TableFunnctionSaveReq.java"
@@ -0,0 +1,75 @@
+package org.yang.crudplus.pojo.req;
+
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import javax.swing.table.TableColumn;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 保存crud生成的方法数据
+ */
+@Data
+public class TableFunnctionSaveReq implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 使用的表名称
+ */
+ private String tableName;
+ /**
+ * 方法名称
+ */
+ private String functionName;
+ /**
+ * 方法类型,insert,update,select,delete
+ */
+ private String functionType;
+ /**
+ * 方法描述
+ */
+ private String functionDescription;
+ /**
+ * 请求pojo对象名称
+ */
+ private String reqFunctionPojoName;
+ /**
+ * 请求pojo对象参数
+ */
+ private List reqFunctionParam;
+ /**
+ * 响应pojo对象名称
+ */
+ private String respFunctionPojoName;
+ /**
+ * 自定义响应对象名称
+ */
+ private String respFunctionCustomPojoName;
+ /**
+ * 响应pojo对象参数
+ */
+ private List respFunctionParam;
+ /**
+ * 真正使用的方法请求类
+ */
+ private String reqPojoUse;
+ /**
+ * reqPojoParamUse
+ */
+ private List reqPojoParamUse;
+ /**
+ * 真正使用的方法请求类字段-使用某些字段进行操作
+ */
+ private List reqPojoParamDataUse;
+ /**
+ * 真正使用的方法响应类
+ */
+ private String respPojoUse;
+ /**
+ * 真正使用的方法响应类的字段
+ */
+ private List respPojoParamUse;
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/testReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/testReq.java"
new file mode 100644
index 0000000..c1633b5
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/req/testReq.java"
@@ -0,0 +1,15 @@
+package org.yang.crudplus.pojo.req;
+
+import java.io.Serializable;
+
+public class testReq implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 姓名
+ */
+ private String name;
+ /**
+ * 年龄
+ */
+ private String age;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/CustomReqRespList.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/CustomReqRespList.java"
new file mode 100644
index 0000000..f82a490
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/CustomReqRespList.java"
@@ -0,0 +1,23 @@
+package org.yang.crudplus.pojo.resp;
+
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 自定义方法中所有的请对/响应象名称
+ */
+@Data
+public class CustomReqRespList implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 自定义的名称
+ */
+ private String customName;
+ /**
+ * 对象的名称
+ */
+ private List columnsList;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableListResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableListResp.java"
new file mode 100644
index 0000000..c0afb98
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableListResp.java"
@@ -0,0 +1,13 @@
+package org.yang.crudplus.pojo.resp;
+
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTable;
+
+import java.io.Serializable;
+import java.util.List;
+@Data
+public class GenTableListResp implements Serializable {
+ private List list;
+
+ private Long total;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableResp.java"
new file mode 100644
index 0000000..ff78821
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTableResp.java"
@@ -0,0 +1,30 @@
+package org.yang.crudplus.pojo.resp;
+
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+
+/**
+* 代码生成表
+* @TableName gen_table
+*/
+@Data
+public class GenTableResp implements Serializable {
+ /**
+ * 表名
+ */
+ private String tableName;
+ /**
+ * 类名
+ */
+ private String className;
+ /**
+ * 说明
+ */
+ private String tableComment;
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTablesUpdateResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTablesUpdateResp.java"
new file mode 100644
index 0000000..818a8d8
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/GenTablesUpdateResp.java"
@@ -0,0 +1,25 @@
+package org.yang.crudplus.pojo.resp;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.vo.GenTableColumnbVo;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 修改代码生成结构表响应
+ */
+@Data
+public class GenTablesUpdateResp implements Serializable {
+ /**
+ * 表信息
+ */
+ private GenTableColumnbVo info;
+
+ private List tables;
+
+ private List rows;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/Response.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/Response.java"
new file mode 100644
index 0000000..bc7f1a9
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/Response.java"
@@ -0,0 +1,31 @@
+package org.yang.crudplus.pojo.resp;
+
+import lombok.Data;
+
+@Data
+public class Response {
+ private int code;
+ private String message;
+ private T data;
+
+ // 默认构造函数,响应成功
+ public Response() {
+ this.code = 200;
+ this.message = "Success";
+ }
+
+ // 带数据的构造函数,响应成功
+ public Response(T data) {
+ this();
+ this.data = data;
+ }
+
+ // 带错误码和消息的构造函数
+ public Response(int code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+}
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionListResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionListResp.java"
new file mode 100644
index 0000000..dc98a17
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionListResp.java"
@@ -0,0 +1,29 @@
+package org.yang.crudplus.pojo.resp;
+
+import lombok.Data;
+import org.yang.crudplus.pojo.TableFunction;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 自定义方法响应集合
+ */
+@Data
+public class TableFunctionListResp implements Serializable {
+ private List list;
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+ private String tableComment;
+ /**
+ * 表方法总数
+ */
+ private int functionNum;
+
+ private Long total;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionResp.java"
new file mode 100644
index 0000000..0326259
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunctionResp.java"
@@ -0,0 +1,54 @@
+package org.yang.crudplus.pojo.resp;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 自定义方法响应
+ */
+@Data
+public class TableFunctionResp implements Serializable {
+
+ /**
+ * 方法id
+ */
+ private Long functionId;
+ /**
+ * 表id
+ */
+ private Long tableId;
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+ private String tableComment;
+ /**
+ * 方法名称
+ */
+ private String functionName;
+ /**
+ * 方法类型(insert,update,delete,selelct)
+ */
+ private String functionType;
+ /**
+ * 方法请求对象名称
+ */
+ private String functionReq;
+
+ /**
+ * 使用的方法响应对象名称
+ */
+ private String functionRespUse;
+
+ /**
+ * 使用的方法请求对象名称
+ */
+ private String functionReqUse;
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunnctionSaveResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunnctionSaveResp.java"
new file mode 100644
index 0000000..8250894
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/resp/TableFunnctionSaveResp.java"
@@ -0,0 +1,74 @@
+package org.yang.crudplus.pojo.resp;
+
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 保存crud生成的方法数据
+ */
+@Data
+public class TableFunnctionSaveResp implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 使用的表名称
+ */
+ private String tableName;
+ /**
+ * 方法名称
+ */
+ private String functionName;
+ /**
+ * 方法类型,insert,update,select,delete
+ */
+ private String functionType;
+ /**
+ * 方法描述
+ */
+ private String functionDescription;
+ /**
+ * 请求pojo对象名称
+ */
+ private String reqFunctionPojoName;
+ /**
+ * 请求pojo对象参数
+ */
+ private List reqFunctionParam;
+ /**
+ * 响应pojo对象名称
+ */
+ private String respFunctionPojoName;
+ /**
+ * 自定义响应对象名称
+ */
+ private String respFunctionCustomPojoName;
+ /**
+ * 响应pojo对象参数
+ */
+ private List respFunctionParam;
+ /**
+ * 真正使用的方法请求类
+ */
+ private String reqPojoUse;
+ /**
+ * reqPojoParamUse
+ */
+ private List reqPojoParamUse;
+ /**
+ * 真正使用的方法请求类字段-使用某些字段进行操作
+ */
+ private List reqPojoParamDataUse;
+ /**
+ * 真正使用的方法响应类
+ */
+ private String respPojoUse;
+ /**
+ * 真正使用的方法响应类的字段
+ */
+ private List respPojoParamUse;
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableCRUD.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableCRUD.java"
new file mode 100644
index 0000000..cee5d1f
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableCRUD.java"
@@ -0,0 +1,127 @@
+package org.yang.crudplus.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.TableFunction;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * crud最终生成的处理类
+ */
+@Data
+public class GenTableCRUD {
+ /**
+ * 编号
+ */
+ private Long tableId;
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+
+ private String tableComment;
+ /**
+ * 关联子表的表名
+ */
+ private String subTableName;
+ /**
+ * 子表关联的外键名
+ */
+ private String subTableFkName;
+ /**
+ * 实体类名称
+ */
+ private String className;
+ /**
+ * 使用的模板(crud单表操作 tree树表操作)
+ */
+ private String tplCategory;
+ /**
+ * 前端模板类型(element-ui模版 element-plus模版)
+ */
+ private String tplWebType;
+ /**
+ * 生成包路径
+ */
+ private String packageName;
+ /**
+ * 生成模块名
+ */
+ private String moduleName;
+ /**
+ * 生成业务名
+ */
+ private String businessName;
+ /**
+ * 生成功能名
+ */
+ private String functionName;
+ /**
+ * 生成功能作者
+ */
+ private String functionAuthor;
+ /**
+ * 生成代码方式(0zip压缩包 1自定义路径)
+ */
+ private String genType;
+ /**
+ * 生成路径(不填默认项目路径)
+ */
+ private String genPath;
+ /**
+ * 其它生成选项
+ */
+ private String options;
+ /**
+ * 创建者
+ */
+ private String createBy;
+ /**
+ * 创建时间
+ */
+
+ private Date createTime;
+ /**
+ * 更新者
+ */
+ private String updateBy;
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 字段信息
+ */
+ private List columns;
+ /**
+ * 子表(主子表)
+ */
+ private GenTableCRUD subTable;
+
+
+ /**
+ * 主键信息
+ */
+ private GenTableColumn pkColumn;
+
+ //自定义方法-扩展信息
+ /**
+ * 方法信息
+ */
+ private List tableFunction;
+
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableColumnbVo.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableColumnbVo.java"
new file mode 100644
index 0000000..2ecee73
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/GenTableColumnbVo.java"
@@ -0,0 +1,106 @@
+package org.yang.crudplus.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * gen_table_column和gen_table关联
+ */
+@Data
+public class GenTableColumnbVo {
+ /**
+ * 编号
+ */
+ @TableId(type = IdType.AUTO)
+ private Long tableId;
+ /**
+ * 表名称
+ */
+ private String tableName;
+ /**
+ * 表描述
+ */
+
+ private String tableComment;
+ /**
+ * 关联子表的表名
+ */
+ private String subTableName;
+ /**
+ * 子表关联的外键名
+ */
+ private String subTableFkName;
+ /**
+ * 实体类名称
+ */
+ private String className;
+ /**
+ * 使用的模板(crud单表操作 tree树表操作)
+ */
+ private String tplCategory;
+ /**
+ * 前端模板类型(element-ui模版 element-plus模版)
+ */
+ private String tplWebType;
+ /**
+ * 生成包路径
+ */
+ private String packageName;
+ /**
+ * 生成模块名
+ */
+ private String moduleName;
+ /**
+ * 生成业务名
+ */
+ private String businessName;
+ /**
+ * 生成功能名
+ */
+ private String functionName;
+ /**
+ * 生成功能作者
+ */
+ private String functionAuthor;
+ /**
+ * 生成代码方式(0zip压缩包 1自定义路径)
+ */
+ private String genType;
+ /**
+ * 生成路径(不填默认项目路径)
+ */
+ private String genPath;
+ /**
+ * 其它生成选项
+ */
+ private String options;
+ /**
+ * 创建者
+ */
+ private String createBy;
+ /**
+ * 创建时间
+ */
+
+ private Date createTime;
+ /**
+ * 更新者
+ */
+ private String updateBy;
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+ /**
+ * 备注
+ */
+ private String remark;
+ private List columns;
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/TableFunctionPlusVo.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/TableFunctionPlusVo.java"
new file mode 100644
index 0000000..be0242f
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/pojo/vo/TableFunctionPlusVo.java"
@@ -0,0 +1,86 @@
+package org.yang.crudplus.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.yang.crudplus.pojo.GenTableColumn;
+
+import java.util.List;
+
+/**
+ * 一个自定义方法的vo
+ */
+@Data
+public class TableFunctionPlusVo {
+ /**
+ * 方法id
+ */
+ private Long functionId;
+ /**
+ * 表id
+ */
+ private Long tableId;
+ /**
+ * 方法名称
+ */
+ private String functionName;
+ /**
+ * 方法类型(insert,update,delete,selelct)
+ */
+ private String functionType;
+ /**
+ * 方法请求对象名称
+ */
+ private String functionReq;
+
+ /**
+ * 方法响应对象名称
+ */
+ private String functionResp;
+ /**
+ * 使用的方法响应对象名称
+ */
+ private String functionRespUse;
+ /**
+ * 使用的方法响应对象名称--方法上面的
+ * 主要用于Select的时候进行区分,List
+ */
+ private String functionRespUsePojo;
+ /**
+ * 导包使用
+ */
+ private String importFunctionRespUse;
+ /**
+ * 使用方法的请求对象名称
+ */
+ private String functionReqUse;
+
+ /**
+ * 方法描述
+ */
+ private String functionDescription;
+
+ /**
+ * 请求类字段
+ */
+ private List reqColumns;
+ /**
+ * 响应类字段
+ */
+ private List respColumns;
+
+
+ /**
+ * 是否使用自定义的请求参数,true使用,false未使用
+ */
+ private Boolean reqUseFlag;
+ /**
+ * 是否使用自定义的响应参数,true使用,false未使用
+ */
+ private Boolean respUseFlag;
+ /**
+ * 请求参数自定义--使用到的字段
+ */
+ private List reqUseColumns;
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/GenTableService.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/GenTableService.java"
new file mode 100644
index 0000000..0ad36c7
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/GenTableService.java"
@@ -0,0 +1,97 @@
+package org.yang.crudplus.service;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.validation.Valid;
+
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.req.GenTableReq;
+import org.yang.crudplus.pojo.req.GenTableSaveReq;
+import org.yang.crudplus.pojo.resp.GenTableListResp;
+import org.yang.crudplus.pojo.resp.GenTablesUpdateResp;
+
+import java.util.List;
+
+public interface GenTableService {
+ /**
+ * 集合查询
+ *
+ * @param genTableReq
+ * @return
+ */
+ public GenTableListResp list(GenTableReq genTableReq);
+
+
+ /**
+ * 查询数据库中有那些表
+ *
+ * @param genTableReq
+ * @return
+ */
+ public List DBlist(GenTableReq genTableReq);
+
+ /**
+ * 导入数据表
+ *
+ * @param tables
+ */
+ public void importTable(String[] tables);
+
+ /**
+ * 导入gen_table,gen_table_column
+ *
+ * @param tableList
+ */
+ public void importGenTable(List tableList);
+
+ /**
+ * 获取表结构详情
+ *
+ * @param tableId
+ * @return
+ */
+ public GenTablesUpdateResp getTableInfo(Long tableId);
+
+ /**
+ * 删除代码生成
+ *
+ * @param tableIds
+ */
+ public void removeById(String[] tableIds);
+
+ /**
+ * 同步表结构--等同于重新导入
+ *
+ * @param tableName
+ */
+ public void synchDb(String tableName);
+
+
+ /**
+ * 保存代码生成表结构配置
+ *
+ * @param req
+ */
+ void saveConfig(GenTableSaveReq req);
+
+
+ /**
+ * 批量生成代码(下载方式)
+ *
+ * @param tableNames 表数组
+ * @return 数据
+ */
+ public byte[] downloadCode(String[] tableNames);
+
+
+ /**
+ * 查询表名称查询字段信息
+ *
+ * @param tableName
+ * @return
+ */
+ public List getTableColumnListByTableName(String tableName);
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionColumnService.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionColumnService.java"
new file mode 100644
index 0000000..8f8067b
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionColumnService.java"
@@ -0,0 +1,15 @@
+package org.yang.crudplus.service;
+
+import java.util.List;
+import org.yang.crudplus.pojo.TableFunctionColumn;
+
+/**
+ * TableFunctionColumnService接口
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+public interface ITableFunctionColumnService
+{
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionService.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionService.java"
new file mode 100644
index 0000000..e4a39de
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/ITableFunctionService.java"
@@ -0,0 +1,65 @@
+package org.yang.crudplus.service;
+
+import java.util.List;
+
+import org.yang.crudplus.pojo.TableFunction;
+import org.yang.crudplus.pojo.req.TableFunctionListReq;
+import org.yang.crudplus.pojo.req.TableFunnctionSaveReq;
+import org.yang.crudplus.pojo.resp.CustomReqRespList;
+import org.yang.crudplus.pojo.resp.TableFunctionListResp;
+import org.yang.crudplus.pojo.resp.TableFunnctionSaveResp;
+
+/**
+ * TableFunctionService接口
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+public interface ITableFunctionService {
+ /**
+ * 保存crud方法信息
+ *
+ * @param req
+ * @return
+ */
+ int saveConfig(TableFunnctionSaveReq req);
+
+
+ /**
+ * 批量生成代码(下载方式)
+ *
+ * @param tableNames 表数组
+ * @return 数据
+ */
+ public byte[] downloadCode(String[] tableNames);
+
+ /**
+ * 自定义方法列表
+ *
+ * @param req
+ * @return
+ */
+ public List list(TableFunctionListReq req);
+
+ /**
+ * 自定义请求类列表
+ * @return
+ */
+ public List customReResoList(String tableType);
+
+ /**
+ * 跟据id查询方法所有信息
+ * @param functionId
+ * @return
+ */
+ TableFunnctionSaveResp functionInfoById(Long functionId);
+
+ /**
+ * 删除方法,跟据id
+ * @param functionId
+ */
+ void deleteFunctionById(Long functionId);
+
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/GenTableServiceImpl.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/GenTableServiceImpl.java"
new file mode 100644
index 0000000..8d9e94c
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/GenTableServiceImpl.java"
@@ -0,0 +1,340 @@
+package org.yang.crudplus.service.impl;
+
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Service;
+
+import org.springframework.transaction.annotation.Transactional;
+import org.yang.crudplus.common.constant.GenConstants;
+import org.yang.crudplus.common.exception.CustomException;
+import org.yang.crudplus.common.utils.GenUtils;
+import org.yang.crudplus.common.utils.StringUtils;
+import org.yang.crudplus.common.utils.VelocityInitializer;
+import org.yang.crudplus.common.utils.VelocityUtils;
+import org.yang.crudplus.mapper.GenTableColumnMapper;
+import org.yang.crudplus.mapper.GenTableMapper;
+import org.yang.crudplus.mapper.TableFunctionColumnMapper;
+import org.yang.crudplus.mapper.TableFunctionMapper;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.TableFunction;
+import org.yang.crudplus.pojo.TableFunctionColumn;
+import org.yang.crudplus.pojo.req.GenTableReq;
+import org.yang.crudplus.pojo.req.GenTableSaveReq;
+import org.yang.crudplus.pojo.resp.GenTableListResp;
+import org.yang.crudplus.pojo.resp.GenTablesUpdateResp;
+import org.yang.crudplus.pojo.vo.GenTableCRUD;
+import org.yang.crudplus.pojo.vo.GenTableColumnbVo;
+import org.yang.crudplus.service.GenTableService;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+@Slf4j
+@Service
+public class GenTableServiceImpl extends ServiceImpl implements GenTableService {
+ @Autowired
+ private GenTableMapper genTableMapper;
+ @Autowired
+ private GenTableColumnMapper genTableColumnMapper;
+
+
+
+
+ /**
+ * 查询导入的表格列表
+ *
+ * @param req
+ * @return
+ */
+ @Override
+ public GenTableListResp list(GenTableReq req) {
+ Page page = new Page<>(req.getPageNum(), req.getPageSize());
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ if (StringUtils.isNotBlank(req.getTableName())) {
+ queryWrapper.like("table_name", req.getTableName());
+ }
+ if (StringUtils.isNotBlank(req.getTableComment())) {
+ queryWrapper.like("table_comment", req.getTableComment());
+ }
+ queryWrapper.orderByDesc("update_time");
+ List records = genTableMapper.selectPage(page, queryWrapper).getRecords();
+ GenTableListResp resp = new GenTableListResp();
+ resp.setList(records);
+ resp.setTotal(page.getTotal());
+ return resp;
+ }
+
+
+ /**
+ * 查询数据库中有那些表
+ *
+ * @param req
+ * @return
+ */
+ @Override
+ public List DBlist(GenTableReq req) {
+ Page page = new Page<>(req.getPageNum(), req.getPageSize());
+ List resp = genTableMapper.DBlist(page, req);
+ return resp;
+ }
+
+
+ /**
+ * 导入数据表
+ *
+ * @param tables
+ */
+ @Transactional
+ @Override
+ public void importTable(String[] tables) {
+ List genTables = genTableMapper.selectDbTableListByNames(tables);
+ importGenTable(genTables);
+ }
+
+ /**
+ * 导入gen_table,gen_table_column
+ *
+ * @param tableList
+ */
+
+ @Override
+ public void importGenTable(List tableList) {
+ try {
+ for (GenTable table : tableList) {
+ String tableName = table.getTableName();
+ //初始化插入数据gen_table
+ GenUtils.initTable(table);
+ //插入数据gen_table
+ int row = genTableMapper.insert(table);
+ if (row > 0) {
+ // 保存列信息
+ List genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+ for (GenTableColumn column : genTableColumns) {
+ GenUtils.initColumnField(column, table);
+ //插入数据到gen_table_column
+ genTableColumnMapper.insert(column);
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new CustomException(400, "导入失败");
+ }
+ }
+
+
+ /**
+ * 获取表结构详情
+ *
+ * @param tableId
+ * @return
+ */
+ public GenTablesUpdateResp getTableInfo(Long tableId) {
+ GenTablesUpdateResp genTablesUpdateResp = new GenTablesUpdateResp();
+ List genTable = genTableMapper.selectGenTableById(tableId);
+ if (genTable.size() > 0) {
+ genTablesUpdateResp.setInfo(genTable.get(0));
+ }
+ //用作联表查询,主-子表
+ List genTables = genTableMapper.selectGenTableAll();
+ List genTableColumns = genTableColumnMapper.selectGenTableColumnListByTableId(tableId);
+ genTablesUpdateResp.setTables(genTables);
+ genTablesUpdateResp.setRows(genTableColumns);
+ return genTablesUpdateResp;
+
+ }
+
+ /**
+ * 删除代码生成
+ *
+ * @param tableIds
+ */
+ @Override
+ public void removeById(String[] tableIds) {
+ for (String tableId : tableIds) {
+ genTableMapper.deleteById(tableId);
+ genTableColumnMapper.delete(new QueryWrapper().eq("table_id", tableId));
+ }
+ }
+
+
+ /**
+ * 同步表结构--等同于重新导入
+ *
+ * @param tableName
+ */
+ @Override
+ public void synchDb(String tableName) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("table_name", tableName);
+ GenTable genTable = new GenTable();
+ try {
+ genTable = genTableMapper.selectOne(queryWrapper);
+ } catch (Exception e) {
+ log.error("重置表结构异常!!!");
+ throw new CustomException(400, "存在相同表名称");
+ }
+ String[] tableIds = new String[]{genTable.getTableId().toString()};
+ removeById(tableIds);
+ importTable(new String[]{tableName});
+
+ }
+
+
+ /**
+ * 保存代码生成表结构配置
+ *
+ * @param req
+ */
+ @Override
+ @Transactional
+ public void saveConfig(GenTableSaveReq req) {
+ GenTable genTable = new GenTable();
+ BeanUtils.copyProperties(req, genTable);
+ int row = genTableMapper.updateById(genTable);
+ if (row > 0) {
+ for (GenTableColumn column : req.getColumns()) {
+ genTableColumnMapper.updateById(column);
+ }
+ }
+ }
+
+ /**
+ * 批量生成代码(下载方式)
+ *
+ * @param tableNames 表数组
+ * @return 数据
+ */
+ public byte[] downloadCode(String[] tableNames) {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(outputStream);
+ for (String tableName : tableNames) {
+ generatorCode(tableName, zip);
+ }
+ IOUtils.closeQuietly(zip);
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * 查询表信息并生成代码
+ */
+ private void generatorCode(String tableName, ZipOutputStream zip) {
+
+ List genTable = genTableMapper.selectGenTableByName(tableName);
+
+
+ GenTableCRUD table = new GenTableCRUD();
+ if (genTable.size() > 0) {
+ GenTableColumnbVo tableColumnbVo = genTable.get(0);
+ BeanUtils.copyProperties(tableColumnbVo, table);
+ }
+
+ setPkColumn(table);
+ //初始化加载模板
+ VelocityInitializer.initVelocity();
+
+ VelocityContext context = VelocityUtils.prepareContext(table);
+
+ // 获取模板列表
+ Map> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+ for (String template : templates.get("single")) {
+ // 渲染模板
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, GenConstants.UTF_8);
+ tpl.merge(context, sw);
+ try {
+ // 添加到zip
+ zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table,null)));
+ IOUtils.write(sw.toString(), zip, GenConstants.UTF_8);
+ IOUtils.closeQuietly(sw);
+ zip.flush();
+ zip.closeEntry();
+ } catch (IOException e) {
+ log.error("渲染模板失败,表名:" + table.getTableName());
+ }
+ }
+ for (String template : templates.get("singleAndCustom")) {
+ // 渲染模板
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, GenConstants.UTF_8);
+ tpl.merge(context, sw);
+ try {
+ // 添加到zip
+ zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table,null)));
+ IOUtils.write(sw.toString(), zip, GenConstants.UTF_8);
+ IOUtils.closeQuietly(sw);
+ zip.flush();
+ zip.closeEntry();
+ } catch (IOException e) {
+ log.error("渲染模板失败,表名:" + table.getTableName());
+ }
+ }
+ }
+
+
+ /**
+ * 设置主键列信息--单表crud
+ *
+ * @param table 业务表信息
+ */
+ public void setPkColumn(GenTableCRUD table) {
+ for (GenTableColumn column : table.getColumns()) {
+ //某个字段是主键
+ if (column.isPk()) {
+ table.setPkColumn(column);
+ break;
+ }
+ }
+ //前面没有找到主键,默认第一个字段是主键
+ if (StringUtils.isNull(table.getPkColumn())) {
+ table.setPkColumn(table.getColumns().get(0));
+ }
+ }
+
+
+ /**
+ * 查询表名称查询字段信息
+ *
+ * @param tableName
+ * @return
+ */
+ @Override
+ public List getTableColumnListByTableName(String tableName) {
+ QueryWrapper genTableQueryWrapper = new QueryWrapper<>();
+ genTableQueryWrapper.eq("table_name", tableName);
+ GenTable genTable = genTableMapper.selectOne(genTableQueryWrapper);
+ if(genTable==null){
+ throw new CustomException(400,"表不存在");
+ }
+ QueryWrapper genTableColumnQueryWrapper = new QueryWrapper<>();
+ genTableColumnQueryWrapper.eq("table_id", genTable.getTableId());
+ return genTableColumnMapper.selectList(genTableColumnQueryWrapper);
+ }
+
+
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionColumnServiceImpl.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionColumnServiceImpl.java"
new file mode 100644
index 0000000..e43687c
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionColumnServiceImpl.java"
@@ -0,0 +1,20 @@
+package org.yang.crudplus.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.yang.crudplus.pojo.TableFunctionColumn;
+import org.yang.crudplus.service.ITableFunctionColumnService;
+
+/**
+ * TableFunctionColumnService业务层处理
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+@Service
+public class TableFunctionColumnServiceImpl implements ITableFunctionColumnService {
+
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionServiceImpl.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionServiceImpl.java"
new file mode 100644
index 0000000..8a848e7
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/java/org/yang/crudplus/service/impl/TableFunctionServiceImpl.java"
@@ -0,0 +1,524 @@
+package org.yang.crudplus.service.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.yang.crudplus.common.constant.GenConstants;
+import org.yang.crudplus.common.exception.CustomException;
+import org.yang.crudplus.common.utils.StringUtils;
+import org.yang.crudplus.common.utils.TypeChecker;
+import org.yang.crudplus.common.utils.VelocityInitializer;
+import org.yang.crudplus.common.utils.VelocityUtils;
+import org.yang.crudplus.mapper.GenTableColumnMapper;
+import org.yang.crudplus.mapper.GenTableMapper;
+import org.yang.crudplus.mapper.TableFunctionColumnMapper;
+import org.yang.crudplus.mapper.TableFunctionMapper;
+import org.yang.crudplus.pojo.GenTable;
+import org.yang.crudplus.pojo.GenTableColumn;
+import org.yang.crudplus.pojo.TableFunction;
+import org.yang.crudplus.pojo.TableFunctionColumn;
+import org.yang.crudplus.pojo.req.TableFunctionListReq;
+import org.yang.crudplus.pojo.req.TableFunnctionSaveReq;
+import org.yang.crudplus.pojo.resp.*;
+import org.yang.crudplus.pojo.vo.GenTableCRUD;
+
+import org.yang.crudplus.pojo.vo.GenTableColumnbVo;
+import org.yang.crudplus.pojo.vo.TableFunctionPlusVo;
+import org.yang.crudplus.service.GenTableService;
+import org.yang.crudplus.service.ITableFunctionService;
+
+import javax.swing.table.TableColumn;
+
+/**
+ * TableFunctionService业务层处理
+ *
+ * @author crud
+ * @date 2024-10-30
+ */
+@Slf4j
+@Service
+public class TableFunctionServiceImpl implements ITableFunctionService {
+ @Autowired
+ private TableFunctionMapper tableFunctionMapper;
+ @Autowired
+ private GenTableMapper genTableMapper;
+ @Autowired
+ private TableFunctionColumnMapper tableFunctionColumnMapper;
+ @Autowired
+ private GenTableColumnMapper genTableColumnMapper;
+ @Autowired
+ private GenTableService genTableService;
+
+ private static List templateList = new ArrayList<>();
+
+ //定义集合,并固定值
+ static {
+ templateList.add("crud/req.java.vm");
+ templateList.add("crud/resp.java.vm");
+ templateList.add("crud/service.java.vm");
+ templateList.add("crud/serviceImpl.java.vm");
+ }
+
+ /**
+ * 保存crud方法信息
+ *
+ * @param req
+ * @return
+ */
+ @Override
+ @Transactional
+ public int saveConfig(TableFunnctionSaveReq req) {
+ //1. 表是否存在
+ String tableName = req.getTableName();
+ QueryWrapper genTableQueryWrapper = new QueryWrapper<>();
+ genTableQueryWrapper.eq("table_name", tableName);
+ GenTable genTable = genTableMapper.selectOne(genTableQueryWrapper);
+ if (genTable == null) {
+ throw new RuntimeException("表不存在");
+ }
+
+
+ TableFunction tableFunction = new TableFunction();
+ tableFunction.setTableId(genTable.getTableId());
+ tableFunction.setFunctionName(req.getFunctionName());
+ tableFunction.setFunctionType(req.getFunctionType());
+ tableFunction.setFunctionDescription(req.getFunctionDescription());
+
+ //编写了自定义请求类和响应类,就默认去生成
+ tableFunction.setFunctionReq(req.getReqFunctionPojoName());//自定义的请求类名称
+ tableFunction.setFunctionReqUse(req.getReqPojoUse());//自定义的请求类是最终使用
+
+ tableFunction.setFunctionRespCustom(req.getRespFunctionCustomPojoName());//自定义对象名称
+
+ tableFunction.setFunctionResp(req.getRespFunctionPojoName());//自定义的响应类名称
+ tableFunction.setFunctionRespUse(req.getRespPojoUse());//自定义的响应类是最终使用
+ int insert = tableFunctionMapper.insert(tableFunction);
+ if (insert < 1) {
+ throw new RuntimeException("保存失败");
+ }
+ //自定义请求对象参数存储
+ List reqPojoParamUse = req.getReqPojoParamUse();
+ if (reqPojoParamUse.size() > 0) {
+ for (GenTableColumn genTableColumn : reqPojoParamUse) {
+ TableFunctionColumn tableFunctionColumn = new TableFunctionColumn();
+ tableFunctionColumn.setColumnId(genTableColumn.getColumnId());
+ tableFunctionColumn.setTableFunctionId(tableFunction.getFunctionId());
+ tableFunctionColumn.setFunctionColumType("req");
+ tableFunctionColumnMapper.insert(tableFunctionColumn);
+ }
+ }
+ List reqPojoParamDataUse = req.getReqPojoParamDataUse();
+ if (reqPojoParamDataUse.size() > 0) {
+ for (GenTableColumn genTableColumn : reqPojoParamDataUse) {
+ TableFunctionColumn tableFunctionColumn = new TableFunctionColumn();
+ tableFunctionColumn.setColumnId(genTableColumn.getColumnId());
+ tableFunctionColumn.setTableFunctionId(tableFunction.getFunctionId());
+ tableFunctionColumn.setFunctionColumType("reqUse");
+ tableFunctionColumnMapper.insert(tableFunctionColumn);
+ }
+ }
+ //响应对象参数字段
+ List respFunctionParam = req.getRespFunctionParam();
+ if (respFunctionParam.size() > 0) {
+ for (GenTableColumn genTableColumn : respFunctionParam) {
+ TableFunctionColumn tableFunctionColumn1 = new TableFunctionColumn();
+ tableFunctionColumn1.setColumnId(genTableColumn.getColumnId());
+ tableFunctionColumn1.setTableFunctionId(tableFunction.getFunctionId());
+ tableFunctionColumn1.setFunctionColumType("resp");
+ tableFunctionColumnMapper.insert(tableFunctionColumn1);
+ }
+ }
+
+ return insert;
+
+ }
+
+
+ /**
+ * 批量生成代码(下载方式)
+ *
+ * @param tableNames 表数组
+ * @return 数据
+ */
+ @Override
+ public byte[] downloadCode(String[] tableNames) {
+ byte[] bytes = downloadCodePlus(tableNames);
+ return bytes;
+ }
+
+
+ /**
+ * 自定义方法列表
+ *
+ * @param req
+ * @return
+ */
+ @Override
+ public List list(TableFunctionListReq req) {
+ //查询存在自定义方法的表
+ List genTables = tableFunctionMapper.selectTableFunction(req.getTableName());
+ List respList = new ArrayList<>();
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ for (GenTable genTable : genTables) {
+ TableFunctionListResp resp = new TableFunctionListResp();
+ resp.setTableName(genTable.getTableName());
+ resp.setTableComment(genTable.getTableComment());
+ queryWrapper.eq("table_id", genTable.getTableId());
+ List tableFunctions = tableFunctionMapper.selectList(queryWrapper);
+ ArrayList tableFunctionResps = new ArrayList<>();
+ for (TableFunction tableFunction : tableFunctions) {
+ TableFunctionResp tableFunctionResp = new TableFunctionResp();
+ BeanUtils.copyProperties(tableFunction, tableFunctionResp);
+ tableFunctionResps.add(tableFunctionResp);
+ }
+ resp.setList(tableFunctionResps);
+ respList.add(resp);
+ }
+ return respList;
+ }
+
+
+ /**
+ * 自定义请求/响应类列表
+ *
+ * @return
+ */
+ @Override
+ public List customReResoList(String tableType) {
+ QueryWrapper tableFunctionQueryWrapper = new QueryWrapper<>();
+ List tableFunctions = tableFunctionMapper.selectList(tableFunctionQueryWrapper);
+ List respLists = new ArrayList<>();
+ for (TableFunction tableFunction : tableFunctions) {
+ CustomReqRespList customReqRespList = new CustomReqRespList();
+ if ("req".equals(tableType)) {
+ if (StringUtils.isNotEmpty(tableFunction.getFunctionReq())) {
+ customReqRespList.setCustomName(tableFunction.getFunctionReq());
+ } else {
+ continue;
+ }
+ }
+ if ("resp".equals(tableType)) {
+ if (StringUtils.isNotEmpty(tableFunction.getFunctionResp())) {
+ customReqRespList.setCustomName(tableFunction.getFunctionResp());
+ } else {
+ continue;
+ }
+ }
+ List reqFunctionColums = genTableColumnMapper.selectFunctionByTableName(tableType, tableFunction.getFunctionId());
+ customReqRespList.setColumnsList(reqFunctionColums);
+ respLists.add(customReqRespList);
+ }
+ respLists = respLists.stream()
+ .collect(Collectors.collectingAndThen(
+ Collectors.toMap(CustomReqRespList::getCustomName, Function.identity(), (existing, replacement) -> existing),
+ map -> new ArrayList<>(map.values())
+ ));
+ //排除子自定义名称为空的值
+ return respLists;
+ }
+
+
+ /**
+ * 跟据id查询方法所有信息
+ *
+ * @param functionId
+ * @return
+ */
+ public TableFunnctionSaveResp functionInfoById(Long functionId) {
+ TableFunnctionSaveResp resp = new TableFunnctionSaveResp();
+ //查询基础信息
+ QueryWrapper tableQuery = new QueryWrapper<>();
+ tableQuery.eq("function_id", functionId);
+ TableFunction tableFunction = tableFunctionMapper.selectOne(tableQuery);
+ QueryWrapper genTableQueryWrapper = new QueryWrapper<>();
+ genTableQueryWrapper.eq("table_id", tableFunction.getTableId());
+ GenTable genTable = genTableMapper.selectOne(genTableQueryWrapper);
+ resp.setTableName(genTable.getTableName());
+ resp.setFunctionName(tableFunction.getFunctionName());
+ resp.setFunctionType(tableFunction.getFunctionType());
+ resp.setFunctionDescription(tableFunction.getFunctionDescription());
+
+ //方法请求对象
+ //逻辑:判断是否存在自定义对象,存在通过方法id和req去table_function_column表找到又那些字段,在拿着字段id去gen_table_column找到字段的详细信息
+ if (StringUtils.isNotEmpty(tableFunction.getFunctionReq())) {
+ resp.setReqFunctionPojoName(tableFunction.getFunctionReq());
+ QueryWrapper tableFunctionColumnQueryWrapper = new QueryWrapper<>();
+ tableFunctionColumnQueryWrapper.eq("table_function_id", tableFunction.getFunctionId());
+ tableFunctionColumnQueryWrapper.eq("function_colum_type", "req");
+ List tableFunctionColumnList = tableFunctionColumnMapper.selectList(tableFunctionColumnQueryWrapper);//拿到字段id集合
+
+ List reqFunctionParam = new ArrayList<>();
+ for (TableFunctionColumn tableFunctionColumn : tableFunctionColumnList) {
+ reqFunctionParam.add(genTableColumnMapper.selectById(tableFunctionColumn.getFunctionColumId()));
+ }
+ resp.setReqFunctionParam(reqFunctionParam);
+ }
+ //响应对象同理前面
+ if (StringUtils.isNotEmpty(tableFunction.getFunctionResp())) {
+ resp.setRespFunctionPojoName(tableFunction.getFunctionResp());
+ QueryWrapper tableFunctionColumnQueryWrapper = new QueryWrapper<>();
+ tableFunctionColumnQueryWrapper.eq("table_function_id", tableFunction.getFunctionId());
+ tableFunctionColumnQueryWrapper.eq("function_colum_type", "resp");
+ List tableFunctionColumnList = tableFunctionColumnMapper.selectList(tableFunctionColumnQueryWrapper);
+ List respFunctionParam = new ArrayList<>();
+ for (TableFunctionColumn tableFunctionColumn : tableFunctionColumnList) {
+ respFunctionParam.add(genTableColumnMapper.selectById(tableFunctionColumn.getFunctionColumId()));
+ }
+ resp.setRespFunctionParam(respFunctionParam);
+ }
+ //自定义响应对象名称
+ if (StringUtils.isNotEmpty(tableFunction.getFunctionRespCustom())) {
+ resp.setRespFunctionCustomPojoName(tableFunction.getFunctionRespCustom());
+ }
+ //真正使用的请求对象名称
+ resp.setReqPojoUse(tableFunction.getFunctionReqUse());
+ //todo 暂时不设置请求对象的参数
+ QueryWrapper tableFunctionColumnQueryWrapper = new QueryWrapper<>();
+ tableFunctionColumnQueryWrapper.eq("table_function_id", tableFunction.getFunctionId());
+ tableFunctionColumnQueryWrapper.eq("function_colum_type", "reqUse");
+ List tableFunctionColumnList = tableFunctionColumnMapper.selectList(tableFunctionColumnQueryWrapper);
+ List reqUseFunctionParam = new ArrayList<>();
+ for (TableFunctionColumn tableFunctionColumn : tableFunctionColumnList) {
+ reqUseFunctionParam.add(genTableColumnMapper.selectById(tableFunctionColumn.getFunctionColumId()));
+ }
+ resp.setReqPojoParamDataUse(reqUseFunctionParam);
+
+ //真正使用的响应对象名称
+ resp.setRespPojoUse(tableFunction.getFunctionRespUse());
+ //todo 暂时不设置响应对象的参数
+
+ return resp;
+
+ }
+
+
+ /**
+ * 删除方法,跟据id
+ *
+ * @param functionId
+ */
+ @Override
+ @Transactional
+ public void deleteFunctionById(Long functionId) {
+ QueryWrapper tableFunctionQueryWrapper = new QueryWrapper<>();
+ tableFunctionQueryWrapper.eq("function_id", functionId);
+ tableFunctionMapper.delete(tableFunctionQueryWrapper);
+ tableFunctionColumnMapper.delete(new QueryWrapper().eq("table_function_id", functionId));
+ }
+
+
+ /**
+ * 进阶-单表生成
+ *
+ * @param tableNames 表数组
+ * @return
+ */
+ public byte[] downloadCodePlus(String[] tableNames) {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(outputStream);
+ for (String tableName : tableNames) {
+ generatorCodePlus(tableName, zip);
+ }
+ IOUtils.closeQuietly(zip);
+ return outputStream.toByteArray();
+ }
+
+
+ private void generatorCodePlus(String tableName, ZipOutputStream zip) {
+
+ List genTable = genTableMapper.selectGenTableByName(tableName);
+
+ GenTableCRUD table = new GenTableCRUD();
+ if (genTable.size() > 0) {
+ GenTableColumnbVo tableColumnbVo = genTable.get(0);
+ BeanUtils.copyProperties(tableColumnbVo, table);
+ }
+ //额外处理
+ //获取自定义方法的
+ Long tableId = table.getTableId();
+ QueryWrapper tableFunctionQueryWrapper = new QueryWrapper<>();
+ tableFunctionQueryWrapper.eq("table_id", tableId);
+ List tableFunctionList = tableFunctionMapper.selectList(tableFunctionQueryWrapper);//该表的所有自定义方法
+
+ List tableFunctionPlusVoList = new ArrayList<>();
+ for (TableFunction tableFunction : tableFunctionList) {
+ TableFunctionPlusVo tableFunctionPlusVo = new TableFunctionPlusVo();
+ BeanUtils.copyProperties(tableFunction, tableFunctionPlusVo);
+
+
+ //自定义请求类不为空,且不等于使用中的,则需要生成新的
+ String functionReq = tableFunction.getFunctionReq();
+ if (StringUtils.isNotEmpty(functionReq) && functionReq.equals(tableFunction.getFunctionReqUse())) {
+ tableFunctionPlusVo.setReqUseFlag(true);
+ List reqFunctionColums = genTableColumnMapper.selectFunctionByTableName("req", tableFunction.getFunctionId());
+ tableFunctionPlusVo.setReqColumns(reqFunctionColums);
+ } else {
+ tableFunctionPlusVo.setReqUseFlag(false);
+ }
+ //不管是否使用自定义请求类,都需要表明使用的请求类的那些字段
+ List reqUseColumns = genTableColumnMapper.selectFunctionByTableName("reqUse", tableFunction.getFunctionId());
+ tableFunctionPlusVo.setReqUseColumns(reqUseColumns);
+
+ //自定义响应类不为空,且不等于使用中的,则需要生成新的
+ String functionResp = tableFunction.getFunctionResp();
+ if (StringUtils.isNotEmpty(functionResp) && functionResp.equals(tableFunction.getFunctionRespUse())) {
+ tableFunctionPlusVo.setRespUseFlag(true);
+ List respFunctionColums = genTableColumnMapper.selectFunctionByTableName("resp", tableFunction.getFunctionId());
+ tableFunctionPlusVo.setRespColumns(respFunctionColums);
+ } else {
+ tableFunctionPlusVo.setRespUseFlag(false);
+
+ }
+
+ tableFunctionPlusVoList.add(tableFunctionPlusVo);
+ }
+ // table.setTableFunction(tableFunctionPlusVoList);
+ setPkColumn(table);
+ //初始化加载模板
+ VelocityInitializer.initVelocity();
+
+ VelocityContext context = VelocityUtils.prepareContext(table);
+
+
+ // 获取模板列表
+ Map> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+ for (String template : templates.get("single")) {
+ // 渲染模板
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, GenConstants.UTF_8);
+ tpl.merge(context, sw);
+ try {
+ // 添加到zip
+ zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table, null)));
+ IOUtils.write(sw.toString(), zip, GenConstants.UTF_8);
+ IOUtils.closeQuietly(sw);
+ zip.flush();
+ zip.closeEntry();
+ } catch (IOException e) {
+ log.error("渲染模板失败,表名:" + table.getTableName(), e);
+ }
+ }
+ for (TableFunctionPlusVo functionPlusVo : tableFunctionPlusVoList) {
+ functionPlusVo.setImportFunctionRespUse(functionPlusVo.getFunctionRespUse());
+ boolean commonReturnType = TypeChecker.isCommonReturnType(functionPlusVo.getFunctionRespUse());
+ if (commonReturnType) {
+ functionPlusVo.setImportFunctionRespUse("null");
+ }
+ functionPlusVo.setFunctionRespUsePojo(functionPlusVo.getFunctionRespUse());
+ if (!commonReturnType) {
+ if ("select".equals(functionPlusVo.getFunctionType())) {
+ functionPlusVo.setFunctionRespUsePojo("List<" + functionPlusVo.getFunctionRespUse() + ">");
+ }
+ }
+ }
+
+
+ //todo service serviceimpl
+ for (String template : templates.get("singleAndCustom")) {
+ context.put("functionList", tableFunctionPlusVoList);//自定义方法集合
+ // 渲染模板
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, GenConstants.UTF_8);
+ tpl.merge(context, sw);
+ try {
+ // 添加到zip
+ zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table, null)));
+ IOUtils.write(sw.toString(), zip, GenConstants.UTF_8);
+ IOUtils.closeQuietly(sw);
+ zip.flush();
+ zip.closeEntry();
+ } catch (IOException e) {
+ log.error("渲染模板失败,表名:" + table.getTableName(), e);
+ }
+ }
+
+ // 生成根据自定义方法生成的文件
+ for (TableFunctionPlusVo functionPlusVo : tableFunctionPlusVoList) {
+ context.put("function", functionPlusVo);
+ context.put("reqClassName", functionPlusVo.getFunctionReq());//请求对象名称
+ context.put("respClassName", functionPlusVo.getFunctionResp());//返回对象名称
+ String reqClassName = functionPlusVo.getFunctionReq();
+ String respClassName = functionPlusVo.getFunctionResp();
+
+
+ for (String template : templates.get("custom")) {
+ String fileName;
+ if (template.contains("req.java.vm")) {
+ Boolean reqUseFlag = functionPlusVo.getReqUseFlag();
+ if (reqUseFlag) {
+ fileName = VelocityUtils.getFileName(template, table, reqClassName);
+ } else {
+ continue;
+ }
+ } else if (template.contains("resp.java.vm")) {
+ Boolean respUseFlag = functionPlusVo.getRespUseFlag();
+ if (respUseFlag) {
+ fileName = VelocityUtils.getFileName(template, table, respClassName);
+ } else {
+ continue;
+ }
+ } else {
+ fileName = VelocityUtils.getFileName(template, table, null);
+ }
+ // 渲染模板
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, GenConstants.UTF_8);
+ tpl.merge(context, sw);
+ try {
+ // 添加到zip
+ zip.putNextEntry(new ZipEntry(fileName));
+ IOUtils.write(sw.toString(), zip, GenConstants.UTF_8);
+ IOUtils.closeQuietly(sw);
+ zip.flush();
+ zip.closeEntry();
+ } catch (IOException e) {
+ log.error("渲染模板失败,表名:" + table.getTableName(), e);
+ }
+
+ }
+ }
+
+
+ }
+
+
+ /**
+ * 设置主键列信息--单表crud
+ *
+ * @param table 业务表信息
+ */
+ public void setPkColumn(GenTableCRUD table) {
+ for (GenTableColumn column : table.getColumns()) {
+ //某个字段是主键
+ if (column.isPk()) {
+ table.setPkColumn(column);
+ break;
+ }
+ }
+ //前面没有找到主键,默认第一个字段是主键
+ if (StringUtils.isNull(table.getPkColumn())) {
+ table.setPkColumn(table.getColumns().get(0));
+ }
+ }
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.properties" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.properties"
new file mode 100644
index 0000000..82acecb
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.properties"
@@ -0,0 +1,3 @@
+spring.application.name=CRUD-PLUS
+mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.yml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.yml"
new file mode 100644
index 0000000..a3f8805
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/application.yml"
@@ -0,0 +1,29 @@
+server:
+ port: 8090
+ servlet:
+ context-path: /curd
+
+spring:
+ profiles:
+ active: dev
+ datasource:
+ # MySQL
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/crud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
+ username: root
+ password: password
+mybatis-plus:
+ configuration:
+ log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+logging:
+ level:
+ com.baomidou.mybatisplus: debug
+ org.yang.crudplus: debug
+ org.apache.ibatis: debug
+
+
+
+
+# 需要指定对应的模板
+generator:
+ template: /template
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/generator.yml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/generator.yml"
new file mode 100644
index 0000000..24bec30
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/generator.yml"
@@ -0,0 +1,10 @@
+# 代码生成
+gen:
+ # 作者
+ author: crud
+ # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
+ packageName: org.yang.crudplus
+ # 自动去除表前缀,默认是false
+ autoRemovePre: false
+ # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
+ tablePrefix: sys_
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/logback.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/logback.xml"
new file mode 100644
index 0000000..963a545
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/logback.xml"
@@ -0,0 +1,16 @@
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/controller.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/controller.java.vm"
new file mode 100644
index 0000000..4c557f1
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/controller.java.vm"
@@ -0,0 +1,74 @@
+package ${packageName}.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.${ClassName}Service;
+
+
+/**
+ * ${functionName}Controller
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@RestController
+@RequestMapping("/${moduleName}/${businessName}")
+public class ${ClassName}Controller {
+ @Autowired
+ private ${ClassName}Service ${className}Service;
+
+ /**
+ * 查询${functionName}列表
+ */
+ @GetMapping("/list")
+ public List<${ClassName}> list(${ClassName} ${className}) {
+ List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+ return list;
+ }
+
+
+ /**
+ * 获取${functionName}详细信息
+ */
+ @GetMapping(value = "/{${pkColumn.javaField}}")
+ public ${ClassName} getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) {
+ return ${className}Service.select${ClassName}By${pkColumn.javaField}(${pkColumn.javaField});
+ }
+
+ /**
+ * 新增${functionName}
+ */
+ @PostMapping
+ public int add(@RequestBody ${ClassName} ${className}) {
+ return ${className}Service.insert${ClassName}(${className});
+ }
+
+ /**
+ * 修改${functionName}
+ */
+
+ @PutMapping
+ public int edit(@RequestBody ${ClassName} ${className}) {
+ return ${className}Service.update${ClassName}(${className});
+ }
+
+ /**
+ * 删除${functionName}
+ */
+
+ @DeleteMapping("/{${pkColumn.javaField}s}")
+ public int remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
+ return ${className}Service.delete${ClassName}By${pkColumn.javaField}s(${pkColumn.javaField}s);
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/domain.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/domain.java.vm"
new file mode 100644
index 0000000..1c71b01
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/domain.java.vm"
@@ -0,0 +1,69 @@
+package ${packageName}.domain;
+
+ #foreach ($import in $importList)
+ import ${import};
+ #end
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+/**
+ * ${tableName}表的实体对象 ${className}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Data
+public class ${ClassName} {
+
+ #foreach ($column in $columns)
+ #if(!$table.isSuperColumn($column.javaField))
+ /** $column.columnComment */
+ #if($column.list)
+ #set($parentheseIndex=$column.columnComment.indexOf("("))
+ #if($parentheseIndex != -1)
+ #set($comment=$column.columnComment.substring(0, $parentheseIndex))
+ #else
+ #set($comment=$column.columnComment)
+ #end
+ #end
+ #if($column.isPk == '1')
+ @TableId
+ #end
+ private $column.javaType $column.javaField;
+ #end
+ #end
+
+ #foreach ($column in $columns)
+ #if(!$table.isSuperColumn($column.javaField))
+ #if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$column.javaField)
+ #else
+ #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ #end
+ public void set${AttrName}($column.javaType $column.javaField) {
+ this.$column.javaField = $column.javaField;
+ }
+
+ public $column.javaType get${AttrName}() {
+ return $column.javaField;
+ }
+ #end
+ #end
+
+ @Override
+ public String toString() {
+ return "${ClassName}{"
+ #foreach ($column in $columns)
+ #if(!$table.isSuperColumn($column.javaField))
+ #if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$column.javaField)
+ #else
+ #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ #end
+ + "${column.javaField}=" + get${AttrName}()
+ #end
+ #end
+ + "}";
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/mapper.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/mapper.java.vm"
new file mode 100644
index 0000000..fb0d31f
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/mapper.java.vm"
@@ -0,0 +1,67 @@
+package ${packageName}.mapper;
+
+import java.util.List;
+import ${packageName}.domain.${ClassName};
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+#if($table.sub)
+import
+import com.baomidou.mybatisplus.core.mapper.BaseMapper; ${packageName}.domain.${subClassName};
+#end
+
+/**
+ * ${functionName}的Mapper接口
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface ${ClassName}Mapper extends BaseMapper<${ClassName}>
+{
+ /**
+ * 查询${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}主键
+ * @return ${functionName}
+ */
+ public ${ClassName} select${ClassName}By${pkColumn.javaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+ /**
+ * 查询${functionName}列表
+ *
+ * @param ${className} ${functionName}
+ * @return ${functionName}集合
+ */
+ public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+ /**
+ * 新增${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 结果
+ */
+ public int insert${ClassName}(${ClassName} ${className});
+
+ /**
+ * 修改${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 结果
+ */
+ public int update${ClassName}(${ClassName} ${className});
+
+ /**
+ * 删除${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}主键
+ * @return 结果
+ */
+ public int delete${ClassName}By${pkColumn.javaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+ /**
+ * 批量删除${functionName}
+ *
+ * @param ${pkColumn.javaField}s 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int delete${ClassName}By${pkColumn.javaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/req.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/req.java.vm"
new file mode 100644
index 0000000..c821fbf
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/req.java.vm"
@@ -0,0 +1,16 @@
+package ${packageName}.domain.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class ${reqClassName} implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ #foreach($column in $function.reqColumns)
+ /**
+ * ${column.columnComment}
+ */
+ private ${column.javaType} ${column.javaField};
+ #end
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/resp.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/resp.java.vm"
new file mode 100644
index 0000000..6de09f4
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/resp.java.vm"
@@ -0,0 +1,16 @@
+package ${packageName}.pojo.resp;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class ${respClassName} implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ #foreach($column in $function.respColumns)
+ /**
+ * ${column.columnComment}
+ */
+ private ${column.javaType} ${column.javaField};
+ #end
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/service.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/service.java.vm"
new file mode 100644
index 0000000..6ee1013
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/service.java.vm"
@@ -0,0 +1,86 @@
+package ${packageName}.service;
+
+import java.util.List;
+
+import ${packageName}.domain.${ClassName};
+#foreach($column in $functionList)
+import ${packageName}.domain.req.${column.functionReqUse};
+#if(${column.importFunctionRespUse}!="null")
+import ${packageName}.domain.resp .${column.functionRespUse};
+#end
+#end
+
+
+
+/**
+ * ${functionName}Service接口
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+
+public interface ${ClassName}Service {
+ /**
+ * 查询${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}主键
+ * @return ${functionName}
+ */
+ public ${ClassName} select${ClassName}By${pkColumn.javaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+ /**
+ * 查询${functionName}列表
+ *
+ * @param ${className} ${functionName}
+ * @return ${functionName}集合
+ */
+ public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+ /**
+ * 新增${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 结果
+ */
+ public int insert${ClassName}(${ClassName} ${className});
+
+ /**
+ * 修改${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 结果
+ */
+ public int update${ClassName}(${ClassName} ${className});
+
+ /**
+ * 批量删除${functionName}
+ *
+ * @param ${pkColumn.javaField}s 需要删除的${functionName}主键集合
+ * @return 结果
+ */
+ public int delete${ClassName}By${pkColumn.javaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+
+ /**
+ * 删除${functionName}信息
+ *
+ * @param ${pkColumn.javaField} ${functionName}主键
+ * @return 结果
+ */
+ public int delete${ClassName}By${pkColumn.javaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+
+
+ #foreach($column in $functionList)
+ /**
+ * #if(${column.functionDescription})
+ ${column.functionDescription}
+ #else
+ ' '
+ #end
+ * @param req
+ * @return ${column.functionRespUse}
+ */
+ public ${column.functionRespUsePojo} ${column.functionName}(${column.functionReqUse} req);
+ #end
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/serviceImpl.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/serviceImpl.java.vm"
new file mode 100644
index 0000000..dd607d5
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/serviceImpl.java.vm"
@@ -0,0 +1,258 @@
+package ${packageName}.service.impl;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+#foreach ($column in $columns)
+ #if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
+ import com.ruoyi.common.utils.DateUtils;
+ #break
+ #end
+#end
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.beans.BeanUtils;
+
+#if($table.sub)
+import java.util.ArrayList;
+
+import com.ruoyi.common.utils.StringUtils;
+import org.springframework.transaction.annotation.Transactional;
+import ${packageName}.domain.${subClassName};
+#end
+import ${packageName}.mapper.${ClassName}Mapper;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.${ClassName}Service;
+
+#foreach($column in $functionList)
+import ${packageName}.domain.req.${column.functionReqUse};
+ #if(${column.importFunctionRespUse}!="null")
+ import ${packageName}.domain.resp .${column.functionRespUse};
+ #end
+#end
+
+/**
+ * ${functionName}Service业务层处理
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Service
+public class ${ClassName}ServiceImpl implements ${ClassName}Service {
+ @Autowired
+ private ${ClassName}Mapper ${className}Mapper;
+
+ /**
+ * 查询${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}主键
+ * @return ${functionName}
+ */
+ @Override
+ public ${ClassName} select${ClassName}By${pkColumn.javaField}(${pkColumn.javaType} ${pkColumn.javaField}) {
+ return ${className}Mapper.select${ClassName}By${pkColumn.javaField}(${pkColumn.javaField});
+ }
+
+ /**
+ * 查询${functionName}列表
+ *
+ * @param ${className} ${functionName}
+ * @return ${functionName}
+ */
+ @Override
+ public List<${ClassName}> select${ClassName}List(${ClassName} ${className}) {
+ return ${className}Mapper.select${ClassName}List(${className});
+ }
+
+ /**
+ * 新增${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 结果
+ */
+ #if($table.sub)
+ @Transactional
+ #end
+ @Override
+ public int insert${ClassName}(${ClassName} ${className}) {
+ #foreach ($column in $columns)
+ #if($column.javaField == 'createTime')
+ ${className}.setCreateTime(DateUtils.getNowDate());
+ #end
+ #end
+ #if($table.sub)
+ int rows = ${className}Mapper.insert${ClassName}(${className});
+ insert${subClassName}(${className});
+ return rows;
+ #else
+ return ${className}Mapper.insert${ClassName}(${className});
+ #end
+ }
+
+ /**
+ * 修改${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 结果
+ */
+ #if($table.sub)
+ @Transactional
+ #end
+ @Override
+ public int update${ClassName}(${ClassName} ${className}) {
+ #foreach ($column in $columns)
+ #if($column.javaField == 'updateTime')
+ ${className}.setUpdateTime(DateUtils.getNowDate());
+ #end
+ #end
+ #if($table.sub)
+ ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.javaField}())
+ ;
+ insert${subClassName}(${className});
+ #end
+ return ${className}Mapper.update${ClassName}(${className});
+ }
+
+ /**
+ * 批量删除${functionName}
+ *
+ * @param ${pkColumn.javaField}s 需要删除的${functionName}主键
+ * @return 结果
+ */
+ #if($table.sub)
+ @Transactional
+ #end
+ @Override
+ public int delete${ClassName}By${pkColumn.javaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s) {
+ #if($table.sub)
+ ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
+ #end
+ return ${className}Mapper.delete${ClassName}By${pkColumn.javaField}s(${pkColumn.javaField}s);
+ }
+
+ /**
+ * 删除${functionName}信息
+ *
+ * @param ${pkColumn.javaField} ${functionName}主键
+ * @return 结果
+ */
+ #if($table.sub)
+ @Transactional
+ #end
+ @Override
+ public int delete${ClassName}By${pkColumn.javaField}(${pkColumn.javaType} ${pkColumn.javaField}) {
+ #if($table.sub)
+ ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
+ #end
+ return ${className}Mapper.delete${ClassName}By${pkColumn.javaField}(${pkColumn.javaField});
+ }
+ #if($table.sub)
+
+ /**
+ * 新增${subTable.functionName}信息
+ *
+ * @param ${className} ${functionName}对象
+ */
+ public void insert${subClassName}(${ClassName} ${className}) {
+ List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
+ ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.javaField}();
+ if (StringUtils.isNotNull(${subclassName}List)) {
+ List<${subClassName}> list = new ArrayList<${subClassName}>();
+ for (${subClassName} ${subclassName} :${subclassName}List)
+ {
+ ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});
+ list.add(${subclassName});
+ }
+ if (list.size() > 0) {
+ ${className}Mapper.batch${subClassName}(list);
+ }
+ }
+ }
+ #end
+
+
+ #foreach($column in $functionList)
+ /**
+ * #if(${column.functionDescription})
+ ${column.functionDescription}
+ #else
+ ' '
+ #end
+ * @param req
+ * @return ${column.functionRespUse}
+ */
+ @Override
+ public ${column.functionRespUsePojo} ${column.functionName}(${column.functionReqUse} req){
+ #if($column.functionType=="insert")
+ ${ClassName} ${className}=new ${ClassName}();
+ #foreach($useColumn in $column.reqUseColumns)
+ #if($useColumn.javaField.length() > 2 && $useColumn.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$useColumn.javaField)
+ #else
+ #set($AttrName=$useColumn.javaField.substring(0,1).toUpperCase() + ${useColumn.javaField.substring(1)})
+ #end
+ ${className}.set${AttrName}(req.get${AttrName}());
+ #end
+ int flag = ${className}Mapper.insert(${className});
+ return flag;
+ #elseif($column.functionType=="delete")
+ QueryWrapper< ${ClassName}> queryWrapper = new QueryWrapper<>();
+ #foreach($useColumn in $column.reqUseColumns)
+ #if($useColumn.javaField.length() > 2 && $useColumn.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$useColumn.javaField)
+ #else
+ #set($AttrName=$useColumn.javaField.substring(0,1).toUpperCase() + ${useColumn.javaField.substring(1)})
+ #end
+ queryWrapper.eq("${useColumn.columnName}", req.get${AttrName}());
+ #end
+ return ${className}Mapper.delete(queryWrapper);
+ #elseif($column.functionType=="update")
+ UpdateWrapper<${ClassName}> updateWrapper = new UpdateWrapper<>();
+ #foreach($useColumn in $column.reqUseColumns)
+ #if($useColumn.javaField.length() > 2 && $useColumn.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$useColumn.javaField)
+ #else
+ #set($AttrName=$useColumn.javaField.substring(0,1).toUpperCase() + ${useColumn.javaField.substring(1)})
+ #end
+ updateWrapper.eq("${useColumn.columnName}", req.get${AttrName}());
+ #end
+ #foreach($useColumn in $column.reqColumns)
+ #if($useColumn.javaField.length() > 2 && $useColumn.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$useColumn.javaField)
+ #else
+ #set($AttrName=$useColumn.javaField.substring(0,1).toUpperCase() + ${useColumn.javaField.substring(1)})
+ #end
+ updateWrapper.set("${useColumn.columnName}", req.get${AttrName}());
+ #end
+ return ${className}Mapper.update(null, updateWrapper);
+ #elseif($column.functionType=="select")
+
+ QueryWrapper<${ClassName}> queryWrapper = new QueryWrapper<>();
+ #foreach($useColumn in $column.reqUseColumns)
+ #if($useColumn.javaField.length() > 2 && $useColumn.javaField.substring(1,2).matches("[A-Z]"))
+ #set($AttrName=$useColumn.javaField)
+ #else
+ #set($AttrName=$useColumn.javaField.substring(0,1).toUpperCase() + ${useColumn.javaField.substring(1)})
+ #end
+ queryWrapper.eq("${useColumn.columnName}", req.get${AttrName}());
+ #end
+ #foreach($respColumn in $column.respColumns)
+ queryWrapper.select("${respColumn.columnName}");
+ #end
+ List<${ClassName}> list = ${className}Mapper.selectList(queryWrapper);
+ List<${column.functionRespUse}> respList = new ArrayList<>();
+ for (${ClassName} ${className} :list){
+ ${column.functionRespUse} resp = new ${column.functionRespUse}();
+ BeanUtils.copyProperties(${className}, resp);
+ respList.add(resp);
+ }
+ return respList;
+
+ #end
+ }
+ #end
+}
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/sub-domain.java.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/sub-domain.java.vm"
new file mode 100644
index 0000000..a3f53eb
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/java/sub-domain.java.vm"
@@ -0,0 +1,76 @@
+package ${packageName}.domain;
+
+#foreach ($import in $subImportList)
+import ${import};
+#end
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * ${subTable.functionName}对象 ${subTableName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public class ${subClassName} extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+#foreach ($column in $subTable.columns)
+#if(!$table.isSuperColumn($column.javaField))
+ /** $column.columnComment */
+#if($column.list)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($parentheseIndex != -1)
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+#elseif($column.javaType == 'Date')
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
+#else
+ @Excel(name = "${comment}")
+#end
+#end
+ private $column.javaType $column.javaField;
+
+#end
+#end
+#foreach ($column in $subTable.columns)
+#if(!$table.isSuperColumn($column.javaField))
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+ public void set${AttrName}($column.javaType $column.javaField)
+ {
+ this.$column.javaField = $column.javaField;
+ }
+
+ public $column.javaType get${AttrName}()
+ {
+ return $column.javaField;
+ }
+#end
+#end
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+#foreach ($column in $subTable.columns)
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+ .append("${column.javaField}", get${AttrName}())
+#end
+ .toString();
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/xml/mapper.xml.vm" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/xml/mapper.xml.vm"
new file mode 100644
index 0000000..c7c95de
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/main/resources/vm/xml/mapper.xml.vm"
@@ -0,0 +1,124 @@
+
+
+
+
+
+ #foreach ($column in $columns)
+
+ #end
+
+
+
+
+ select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end
+ from ${tableName}
+
+
+
+
+
+ #foreach($column in $columns)
+ #set($queryType=$column.queryType)
+ #set($javaField=$column.javaField)
+ #set($javaType=$column.javaType)
+ #set($columnName=$column.columnName)
+ #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ #if($column.queryType == "EQ")
+
+ and $columnName = #{$javaField}
+
+ #elseif($queryType == "NE")
+
+ and $columnName != #{$javaField}
+
+ #elseif($queryType == "GT")
+
+ and $columnName > #{$javaField}
+
+ #elseif($queryType == "GTE")
+
+ and $columnName >= #{$javaField}
+
+ #elseif($queryType == "LT")
+
+ and $columnName < #{$javaField}
+
+ #elseif($queryType == "LTE")
+
+ and $columnName <= #{$javaField}
+
+ #elseif($queryType == "LIKE")
+
+ and $columnName like concat('%', #{$javaField}, '%')
+
+ #elseif($queryType == "BETWEEN")
+
+ and $columnName between #{params.begin$AttrName} and #{params.end$AttrName}
+
+ #end
+ #end
+
+
+
+
+
+
+
+ where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+
+
+
+
+ insert into ${tableName}
+
+ #foreach($column in $columns)
+ #if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+ $column.columnName,
+
+ #end
+ #end
+
+
+ #foreach($column in $columns)
+ #if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+ #{$column.javaField},
+
+ #end
+ #end
+
+
+
+
+ update ${tableName}
+
+ #foreach($column in $columns)
+ #if($column.columnName != $pkColumn.columnName)
+ $column.columnName =
+ #{$column.javaField},
+
+ #end
+ #end
+
+ where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+
+
+
+ delete
+ from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+
+
+
+ delete from ${tableName} where ${pkColumn.columnName} in
+
+ #{${pkColumn.javaField}}
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/test/java/org/yang/crudplus/CrudPlusApplicationTests.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/test/java/org/yang/crudplus/CrudPlusApplicationTests.java"
new file mode 100644
index 0000000..dff118a
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-plus/src/test/java/org/yang/crudplus/CrudPlusApplicationTests.java"
@@ -0,0 +1,13 @@
+package org.yang.crudplus;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class CrudPlusApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/pom.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/pom.xml"
new file mode 100644
index 0000000..7f30657
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/pom.xml"
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+
+ org.yang
+ crud
+ 0.0.1-SNAPSHOT
+ ../../crud/pom.xml
+
+ org.yang
+ crud-test
+ 0.0.1-SNAPSHOT
+ crud-test
+ crud-test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ 3.5.7
+
+
+ org.projectlombok
+ lombok
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/CrudTestApplication.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/CrudTestApplication.java"
new file mode 100644
index 0000000..7b2d0f6
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/CrudTestApplication.java"
@@ -0,0 +1,18 @@
+package org.yang.crudplus;
+
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@SpringBootApplication
+@MapperScan("org.yang.crudplus.mapper")
+@EnableTransactionManagement
+public class CrudTestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CrudTestApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/controller/StudentsController.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/controller/StudentsController.java"
new file mode 100644
index 0000000..fe13857
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/controller/StudentsController.java"
@@ -0,0 +1,74 @@
+package org.yang.crudplus.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import org.yang.crudplus.domain.Students;
+import org.yang.crudplus.service.StudentsService;
+
+
+/**
+ * 学生表Controller
+ *
+ * @author crud
+ * @date 2024-11-02
+ */
+@RestController
+@RequestMapping("/crudplus/students")
+public class StudentsController {
+ @Autowired
+ private StudentsService studentsService;
+
+ /**
+ * 查询学生表列表
+ */
+ @GetMapping("/list")
+ public List list(Students students) {
+ List list = studentsService.selectStudentsList(students);
+ return list;
+ }
+
+
+ /**
+ * 获取学生表详细信息
+ */
+ @GetMapping(value = "/{id}")
+ public Students getInfo(@PathVariable("id") Long id) {
+ return studentsService.selectStudentsByid(id);
+ }
+
+ /**
+ * 新增学生表
+ */
+ @PostMapping
+ public int add(@RequestBody Students students) {
+ return studentsService.insertStudents(students);
+ }
+
+ /**
+ * 修改学生表
+ */
+
+ @PutMapping
+ public int edit(@RequestBody Students students) {
+ return studentsService.updateStudents(students);
+ }
+
+ /**
+ * 删除学生表
+ */
+
+ @DeleteMapping("/{ids}")
+ public int remove(@PathVariable Long[] ids) {
+ return studentsService.deleteStudentsByids(ids);
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/Students.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/Students.java"
new file mode 100644
index 0000000..324a69d
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/Students.java"
@@ -0,0 +1,84 @@
+package org.yang.crudplus.domain;
+
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+/**
+ * students表的实体对象 students
+ *
+ * @author crud
+ * @date 2024-11-02
+ */
+@Data
+public class Students {
+
+ /** id */
+ @TableId
+ private Long id;
+ /** 姓名 */
+ private String name;
+ /** 年龄 */
+ private Long age;
+ /** 类型 */
+ private String type;
+ /** 手机号码 */
+ private String phone;
+ /** 用户id */
+ private Long userId;
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Long getId() {
+ return id;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setAge(Long age) {
+ this.age = age;
+ }
+
+ public Long getAge() {
+ return age;
+ }
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ @Override
+ public String toString() {
+ return "Students{"
+ + "id=" + getId()
+ + "name=" + getName()
+ + "age=" + getAge()
+ + "type=" + getType()
+ + "phone=" + getPhone()
+ + "userId=" + getUserId()
+ + "}";
+ }
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/deletcStudengtsReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/deletcStudengtsReq.java"
new file mode 100644
index 0000000..ccdb3b1
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/deletcStudengtsReq.java"
@@ -0,0 +1,14 @@
+package org.yang.crudplus.domain.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class deletcStudengtsReq implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ private Long id;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/insertStudentsReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/insertStudentsReq.java"
new file mode 100644
index 0000000..039ed71
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/insertStudentsReq.java"
@@ -0,0 +1,26 @@
+package org.yang.crudplus.domain.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class insertStudentsReq implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 姓名
+ */
+ private String name;
+ /**
+ * 年龄
+ */
+ private Long age;
+ /**
+ * 类型
+ */
+ private String type;
+ /**
+ * 手机号码
+ */
+ private String phone;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/selectStudentByIdReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/selectStudentByIdReq.java"
new file mode 100644
index 0000000..d64baa2
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/selectStudentByIdReq.java"
@@ -0,0 +1,14 @@
+package org.yang.crudplus.domain.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class selectStudentByIdReq implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ private Long id;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/updateByAgeReq.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/updateByAgeReq.java"
new file mode 100644
index 0000000..9a03ab5
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/req/updateByAgeReq.java"
@@ -0,0 +1,14 @@
+package org.yang.crudplus.domain.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class updateByAgeReq implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 年龄
+ */
+ private Long age;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/selectStudentByIdResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/selectStudentByIdResp.java"
new file mode 100644
index 0000000..2aedc01
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/selectStudentByIdResp.java"
@@ -0,0 +1,26 @@
+package org.yang.crudplus.domain.resp;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class selectStudentByIdResp implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 姓名
+ */
+ private String name;
+ /**
+ * 年龄
+ */
+ private Long age;
+ /**
+ * 类型
+ */
+ private String type;
+ /**
+ * 手机号码
+ */
+ private String phone;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/updateByAgeResp.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/updateByAgeResp.java"
new file mode 100644
index 0000000..80714bf
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/domain/resp/updateByAgeResp.java"
@@ -0,0 +1,26 @@
+package org.yang.crudplus.domain.resp;
+
+import lombok.Data;
+
+import java.io.Serializable;
+@Data
+public class updateByAgeResp implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 姓名
+ */
+ private String name;
+ /**
+ * 年龄
+ */
+ private Long age;
+ /**
+ * 类型
+ */
+ private String type;
+ /**
+ * 手机号码
+ */
+ private String phone;
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/mapper/StudentsMapper.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/mapper/StudentsMapper.java"
new file mode 100644
index 0000000..976e35a
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/mapper/StudentsMapper.java"
@@ -0,0 +1,63 @@
+package org.yang.crudplus.mapper;
+
+import java.util.List;
+import org.yang.crudplus.domain.Students;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+
+/**
+ * 学生表的Mapper接口
+ *
+ * @author crud
+ * @date 2024-11-02
+ */
+public interface StudentsMapper extends BaseMapper
+{
+ /**
+ * 查询学生表
+ *
+ * @param id 学生表主键
+ * @return 学生表
+ */
+ public Students selectStudentsByid(Long id);
+
+ /**
+ * 查询学生表列表
+ *
+ * @param students 学生表
+ * @return 学生表集合
+ */
+ public List selectStudentsList(Students students);
+
+ /**
+ * 新增学生表
+ *
+ * @param students 学生表
+ * @return 结果
+ */
+ public int insertStudents(Students students);
+
+ /**
+ * 修改学生表
+ *
+ * @param students 学生表
+ * @return 结果
+ */
+ public int updateStudents(Students students);
+
+ /**
+ * 删除学生表
+ *
+ * @param id 学生表主键
+ * @return 结果
+ */
+ public int deleteStudentsByid(Long id);
+
+ /**
+ * 批量删除学生表
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteStudentsByids(Long[] ids);
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/StudentsService.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/StudentsService.java"
new file mode 100644
index 0000000..8e0e365
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/StudentsService.java"
@@ -0,0 +1,111 @@
+package org.yang.crudplus.service;
+
+import java.util.List;
+
+import org.yang.crudplus.domain.Students;
+import org.yang.crudplus.domain.req.insertStudentsReq;
+import org.yang.crudplus.domain.req.deletcStudengtsReq;
+import org.yang.crudplus.domain.req.selectStudentByIdReq;
+import org.yang.crudplus.domain.resp .selectStudentByIdResp;
+import org.yang.crudplus.domain.req.insertStudentsReq;
+import org.yang.crudplus.domain.resp .selectStudentByIdResp;
+import org.yang.crudplus.domain.req.updateByAgeReq;
+import org.yang.crudplus.domain.resp .updateByAgeResp;
+
+
+
+/**
+ * 学生表Service接口
+ *
+ * @author crud
+ * @date 2024-11-02
+ */
+
+public interface StudentsService {
+ /**
+ * 查询学生表
+ *
+ * @param id 学生表主键
+ * @return 学生表
+ */
+ public Students selectStudentsByid(Long id);
+
+ /**
+ * 查询学生表列表
+ *
+ * @param students 学生表
+ * @return 学生表集合
+ */
+ public List selectStudentsList(Students students);
+
+ /**
+ * 新增学生表
+ *
+ * @param students 学生表
+ * @return 结果
+ */
+ public int insertStudents(Students students);
+
+ /**
+ * 修改学生表
+ *
+ * @param students 学生表
+ * @return 结果
+ */
+ public int updateStudents(Students students);
+
+ /**
+ * 批量删除学生表
+ *
+ * @param ids 需要删除的学生表主键集合
+ * @return 结果
+ */
+ public int deleteStudentsByids(Long[] ids);
+
+ /**
+ * 删除学生表信息
+ *
+ * @param id 学生表主键
+ * @return 结果
+ */
+ public int deleteStudentsByid(Long id);
+
+
+
+ /**
+ * 新增学生
+
+ * @param req
+ * @return void
+ */
+ public void insertStudents(insertStudentsReq req);
+ /**
+ * 跟据id删除学生信息
+
+ * @param req
+ * @return void
+ */
+ public void deletcStudengtsById(deletcStudengtsReq req);
+ /**
+ * 跟据id查询
+
+ * @param req
+ * @return selectStudentByIdResp
+ */
+ public List selectStudentById(selectStudentByIdReq req);
+ /**
+ * 跟据姓名查询
+
+ * @param req
+ * @return selectStudentByIdResp
+ */
+ public List selectStudentByName(insertStudentsReq req);
+ /**
+ * 测试update
+
+ * @param req
+ * @return updateByAgeResp
+ */
+ public updateByAgeResp updateTest(updateByAgeReq req);
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/impl/StudentsServiceImpl.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/impl/StudentsServiceImpl.java"
new file mode 100644
index 0000000..9ca9f1f
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/java/org/yang/crudplus/service/impl/StudentsServiceImpl.java"
@@ -0,0 +1,193 @@
+package org.yang.crudplus.service.impl;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.beans.BeanUtils;
+
+import org.yang.crudplus.mapper.StudentsMapper;
+import org.yang.crudplus.domain.Students;
+import org.yang.crudplus.service.StudentsService;
+
+import org.yang.crudplus.domain.req.insertStudentsReq;
+import org.yang.crudplus.domain.req.deletcStudengtsReq;
+import org.yang.crudplus.domain.req.selectStudentByIdReq;
+ import org.yang.crudplus.domain.resp .selectStudentByIdResp;
+import org.yang.crudplus.domain.req.insertStudentsReq;
+ import org.yang.crudplus.domain.resp .selectStudentByIdResp;
+import org.yang.crudplus.domain.req.updateByAgeReq;
+ import org.yang.crudplus.domain.resp .updateByAgeResp;
+
+/**
+ * 学生表Service业务层处理
+ *
+ * @author crud
+ * @date 2024-11-02
+ */
+@Service
+public class StudentsServiceImpl implements StudentsService {
+ @Autowired
+ private StudentsMapper studentsMapper;
+
+ /**
+ * 查询学生表
+ *
+ * @param id 学生表主键
+ * @return 学生表
+ */
+ @Override
+ public Students selectStudentsByid(Long id) {
+ return studentsMapper.selectStudentsByid(id);
+ }
+
+ /**
+ * 查询学生表列表
+ *
+ * @param students 学生表
+ * @return 学生表
+ */
+ @Override
+ public List selectStudentsList(Students students) {
+ return studentsMapper.selectStudentsList(students);
+ }
+
+ /**
+ * 新增学生表
+ *
+ * @param students 学生表
+ * @return 结果
+ */
+ @Override
+ public int insertStudents(Students students) {
+ return studentsMapper.insertStudents(students);
+ }
+
+ /**
+ * 修改学生表
+ *
+ * @param students 学生表
+ * @return 结果
+ */
+ @Override
+ public int updateStudents(Students students) {
+ return studentsMapper.updateStudents(students);
+ }
+
+ /**
+ * 批量删除学生表
+ *
+ * @param ids 需要删除的学生表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteStudentsByids(Long[] ids) {
+ return studentsMapper.deleteStudentsByids(ids);
+ }
+
+ /**
+ * 删除学生表信息
+ *
+ * @param id 学生表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteStudentsByid(Long id) {
+ return studentsMapper.deleteStudentsByid(id);
+ }
+
+
+ /**
+ * 新增学生
+
+ * @param req
+ * @return void
+ */
+ @Override
+ public void insertStudents(insertStudentsReq req){
+ Students students=new Students();
+ students.setName(req.getName());
+ students.setAge(req.getAge());
+ students.setType(req.getType());
+ students.setPhone(req.getPhone());
+ int flag = studentsMapper.insert(students);
+
+ }
+ /**
+ * 跟据id删除学生信息
+
+ * @param req
+ * @return void
+ */
+ @Override
+ public void deletcStudengtsById(deletcStudengtsReq req){
+ QueryWrapper< Students> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("id", req.getId());
+ studentsMapper.delete(queryWrapper);
+
+ }
+ /**
+ * 跟据id查询
+
+ * @param req
+ * @return selectStudentByIdResp
+ */
+ @Override
+ public List selectStudentById(selectStudentByIdReq req){
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("id", req.getId());
+ queryWrapper.select("name");
+ queryWrapper.select("age");
+ queryWrapper.select("type");
+ queryWrapper.select("phone");
+ List list = studentsMapper.selectList(queryWrapper);
+ List respList = new ArrayList<>();
+ for (Students students :list){
+ selectStudentByIdResp resp = new selectStudentByIdResp();
+ BeanUtils.copyProperties(students, resp);
+ respList.add(resp);
+ }
+ return respList;
+
+ }
+ /**
+ * 跟据姓名查询
+
+ * @param req
+ * @return selectStudentByIdResp
+ */
+ @Override
+ public List selectStudentByName(insertStudentsReq req){
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("name", req.getName());
+ List list = studentsMapper.selectList(queryWrapper);
+ List respList = new ArrayList<>();
+ for (Students students :list){
+ selectStudentByIdResp resp = new selectStudentByIdResp();
+ BeanUtils.copyProperties(students, resp);
+ respList.add(resp);
+ }
+ return respList;
+
+ }
+ /**
+ * 测试update
+
+ * @param req
+ * @return updateByAgeResp
+ */
+ @Override
+ public updateByAgeResp updateTest(updateByAgeReq req){
+ QueryWrapper< Students> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("age", req.getAge());
+ studentsMapper.delete(queryWrapper);
+ return null;
+ }
+}
+
+
+
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/application.yml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/application.yml"
new file mode 100644
index 0000000..627ad53
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/application.yml"
@@ -0,0 +1,18 @@
+mybatis:
+ # 搜索指定包别名
+ typeAliasesPackage: org.yang.**.domain
+ # 配置mapper的扫描,找到所有的mapper.xml映射文件
+ mapperLocations: classpath*:mapper/**/*Mapper.xml
+
+
+spring:
+ profiles:
+ active: dev
+ datasource:
+ # MySQL
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/crud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
+ username: root
+ password: password
+server:
+ port: 8099
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/mapper/crudplus/StudentsMapper.xml" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/mapper/crudplus/StudentsMapper.xml"
new file mode 100644
index 0000000..d8d2f9c
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/main/resources/mapper/crudplus/StudentsMapper.xml"
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select id, name, age, type, phone, user_id
+ from students
+
+
+
+
+
+
+ and id = #{id}
+
+
+ and name like concat('%', #{name}, '%')
+
+
+ and age = #{age}
+
+
+ and type = #{type}
+
+
+ and phone = #{phone}
+
+
+ and user_id = #{userId}
+
+
+
+
+
+
+
+
+ where id = #{id}
+
+
+
+
+ insert into students
+
+ id,
+
+ name,
+
+ age,
+
+ type,
+
+ phone,
+
+ user_id,
+
+
+
+ #{id},
+
+ #{name},
+
+ #{age},
+
+ #{type},
+
+ #{phone},
+
+ #{userId},
+
+
+
+
+
+ update students
+
+ name =
+ #{name},
+
+ age =
+ #{age},
+
+ type =
+ #{type},
+
+ phone =
+ #{phone},
+
+ user_id =
+ #{userId},
+
+
+ where id = #{id}
+
+
+
+ delete
+ from students where id = #{id}
+
+
+
+ delete from students where id in
+
+ #{id}
+
+
+
+
\ No newline at end of file
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/test/java/org/yang/crudtest/CrudTestApplicationTests.java" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/test/java/org/yang/crudtest/CrudTestApplicationTests.java"
new file mode 100644
index 0000000..bfa4f1b
--- /dev/null
+++ "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/crud-test/src/test/java/org/yang/crudtest/CrudTestApplicationTests.java"
@@ -0,0 +1,14 @@
+package org.yang.crudtest;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.yang.crudplus.CrudTestApplication;
+
+@SpringBootTest(classes = CrudTestApplication.class)
+class CrudTestApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git "a/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img.png" "b/CRUD-PLUS\344\273\243\347\240\201\347\224\237\346\210\220/image/img.png"
new file mode 100644
index 0000000000000000000000000000000000000000..96e457a21e34023c227228d1d667b221e70b89e3
GIT binary patch
literal 22906
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