From 2ef66566d4befc054a5657c475866e78702f0bea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 12 Jul 2026 11:57:39 +0800 Subject: [PATCH] feat(codegen): 完善 UniApp Wot 代码生成 --- yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/api/api.ts.vm | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/components/breadcrumb_tree.vue.vm | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail/index.vue.vm | 49 ++++++++++++++++++++++++++++--------------------- yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_erp.vue.vm | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_master.vue.vm | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form/index.vue.vm | 705 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------------------- yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form_sub_erp.vue.vm | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/index_tree.vue.vm | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java | 14 +++++++++----- yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineUniappTest.java | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/assert.json | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/ErrorCodeConstants_手动操作 | 6 ++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentContactDO | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentContactMapper | 34 ++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentController | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentDO | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentMapper | 30 ++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentPageReqVO | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentSaveReqVO | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentService | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImpl | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImplTest | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherDO | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherMapper | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/h2 | 17 +++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/sql | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/ts/index | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/detail/index | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/form/index | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/index | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/search-form | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-contact/form/index | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-teacher/form/index | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/xml/InfraStudentMapper | 12 ++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/assert.json | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/ErrorCodeConstants_手动操作 | 3 +++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactDO | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactMapper | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentController | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentDO | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentMapper | 30 ++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentPageReqVO | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentSaveReqVO | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentService | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImpl | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImplTest | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherDO | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherMapper | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/h2 | 17 +++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/sql | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/ts/index | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/detail/index | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/form/index | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/index | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/search-form | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/xml/InfraStudentMapper | 12 ++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/assert.json | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/ErrorCodeConstants_手动操作 | 3 +++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactDO | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactMapper | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentController | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentDO | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentMapper | 30 ++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentPageReqVO | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentSaveReqVO | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentService | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImpl | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImplTest | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherDO | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherMapper | 32 ++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/h2 | 17 +++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/sql | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/ts/index | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/detail/index | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/form/index | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/index | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/search-form | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/xml/InfraStudentMapper | 12 ++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/ts/index | 6 +++--- yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/detail/index | 43 ++++++++++++++++++++++--------------------- yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/form/index | 36 ++++++++++++++++++++---------------- yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/assert.json | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/ErrorCodeConstants_手动操作 | 8 ++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryController | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryDO | 40 ++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryListReqVO | 15 +++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryMapper | 34 ++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO | 25 +++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategorySaveReqVO | 23 +++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryService | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImpl | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImplTest | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/h2 | 10 ++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/sql | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/ts/index | 34 ++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/breadcrumb | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/detail/index | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/form/index | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/index | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/search-form | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/xml/InfraCategoryMapper | 12 ++++++++++++ 105 files changed, 10321 insertions(+), 190 deletions(-) create mode 100644 yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/components/breadcrumb_tree.vue.vm create mode 100644 yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_erp.vue.vm create mode 100644 yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_master.vue.vm create mode 100644 yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form_sub_erp.vue.vm create mode 100644 yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/index_tree.vue.vm create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/assert.json create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/ErrorCodeConstants_手动操作 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentContactDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentContactMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentController create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentPageReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentSaveReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentService create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImpl create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImplTest create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/h2 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/sql create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/ts/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/detail/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/form/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/search-form create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-contact/form/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-teacher/form/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/xml/InfraStudentMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/assert.json create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/ErrorCodeConstants_手动操作 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentController create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentPageReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentSaveReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentService create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImpl create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImplTest create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/h2 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/sql create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/ts/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/detail/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/form/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/search-form create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/xml/InfraStudentMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/assert.json create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/ErrorCodeConstants_手动操作 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentController create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentPageReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentSaveReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentService create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImpl create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImplTest create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/h2 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/sql create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/ts/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/detail/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/form/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/search-form create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/xml/InfraStudentMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/assert.json create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/ErrorCodeConstants_手动操作 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryController create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryDO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryListReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryMapper create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategorySaveReqVO create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryService create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImpl create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImplTest create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/h2 create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/sql create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/ts/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/breadcrumb create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/detail/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/form/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/index create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/search-form create mode 100644 yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/xml/InfraCategoryMapper diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index d675558..9a1f530 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -152,6 +152,16 @@ public class CodegenEngine { vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/form/index.vue")) .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/detail/index.vue"), vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/detail/index.vue")) + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/index_tree.vue"), + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/index.vue")) + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("components/breadcrumb_tree.vue"), + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/components/breadcrumb.vue")) + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/detail_master.vue"), + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/detail/index.vue")) + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/detail_erp.vue"), + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/detail/index.vue")) + .put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/form_sub_erp.vue"), + vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/${subSimpleClassName_strikeCase}/form/index.vue")) // VUE3_VBEN2_ANTD_SCHEMA .put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/data.ts"), vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) @@ -380,12 +390,17 @@ public class CodegenEngine { // 2. 执行生成 Map result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 + Map generatedSources = Maps.newHashMapWithExpectedSize(templates.size()); templates.forEach((vmPath, filePath) -> { - // 2.1 特殊:主子表专属逻辑 + // 2.1 特殊:主子表、Uniapp 树表使用独立页面模版 + if (isVue3AdminUniappTemplate(vmPath) && !matchVue3AdminUniappTemplate(table, vmPath)) { + return; + } + // 2.2 特殊:主子表专属逻辑 if (isSubTemplate(vmPath)) { - generateSubCode(table, subTables, result, vmPath, filePath, bindingMap); + generateSubCode(table, subTables, result, generatedSources, vmPath, filePath, bindingMap); return; - // 2.2 特殊:树表专属逻辑 + // 2.3 特殊:树表专属逻辑 } else if (isPageReqVOTemplate(vmPath)) { // 减少多余的类生成,例如说 PageVO.java 类 if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { @@ -402,15 +417,21 @@ public class CodegenEngine { return; } } - // 2.3 默认生成 - generateCode(result, vmPath, filePath, bindingMap); + // 2.4 默认生成 + generateCode(result, generatedSources, vmPath, filePath, bindingMap); }); return result; } - private void generateCode(Map result, String vmPath, + private void generateCode(Map result, Map generatedSources, String vmPath, String filePath, Map bindingMap) { filePath = formatFilePath(filePath, bindingMap); + String source = vmPath + (bindingMap.containsKey("subIndex") ? "[subIndex=" + bindingMap.get("subIndex") + "]" : ""); + String previousSource = generatedSources.putIfAbsent(filePath, source); + if (previousSource != null) { + throw new IllegalStateException(String.format("生成文件路径重复:%s,来源模板:%s、%s", + filePath, previousSource, source)); + } String content = templateEngine.getTemplate(vmPath).render(bindingMap); // 格式化代码 content = prettyCode(content, vmPath); @@ -418,7 +439,7 @@ public class CodegenEngine { } private void generateSubCode(CodegenTableDO table, List subTables, - Map result, String vmPath, + Map result, Map generatedSources, String vmPath, String filePath, Map bindingMap) { // 没有子表,所以不生成 if (CollUtil.isEmpty(subTables)) { @@ -441,7 +462,7 @@ public class CodegenEngine { // 逐个生成 for (int i = 0; i < subTables.size(); i++) { bindingMap.put("subIndex", i); - generateCode(result, vmPath, filePath, bindingMap); + generateCode(result, generatedSources, vmPath, filePath, bindingMap); } bindingMap.remove("subIndex"); } @@ -482,6 +503,13 @@ public class CodegenEngine { if (StrUtil.count(content, "DICT_TYPE.") == 0) { content = StrUtils.removeLineContains(content, "DICT_TYPE"); } + // Vue3 Admin UniApp:清理空白行,并补充文件末尾换行,满足 ESLint 格式要求 + if (vmPath.contains("vue3_admin_uniapp")) { + content = content.replaceAll("(?m)^[\\t ]+$", ""); + if (!content.endsWith("\n")) { + content += "\n"; + } + } return content; } @@ -734,6 +762,33 @@ public class CodegenEngine { return path.contains("_sub"); } + private static boolean isVue3AdminUniappTemplate(String path) { + return path.contains("codegen/vue3_admin_uniapp/"); + } + + /** + * 匹配 Uniapp 不同表类型的专用页面模版 + */ + private static boolean matchVue3AdminUniappTemplate(CodegenTableDO table, String path) { + boolean tree = CodegenTemplateTypeEnum.isTree(table.getTemplateType()); + boolean masterSubmit = ObjectUtil.equals(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_NORMAL.getType()) + || ObjectUtil.equals(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_INNER.getType()); + boolean masterErp = ObjectUtil.equals(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_ERP.getType()); + if (path.contains("_tree")) { + return tree; + } + if (path.contains("detail_master")) { + return masterSubmit; + } + if (path.contains("_erp")) { + return masterErp; + } + if (tree && path.endsWith("views/index.vue.vm")) { + return false; + } + return !(masterSubmit || masterErp) || !path.endsWith("views/detail/index.vue.vm"); + } + private static boolean isPageReqVOTemplate(String path) { return path.contains("pageReqVO"); } diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/api/api.ts.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/api/api.ts.vm index 6c5d706..209b540 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/api/api.ts.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/api/api.ts.vm @@ -1,4 +1,6 @@ +#if ($table.templateType != 2) import type { PageParam, PageResult } from '@/http/types' +#end import { http } from '@/http/http' #set ($primaryJavaType = $primaryColumn.javaType.toLowerCase()) @@ -7,30 +9,72 @@ import { http } from '@/http/http' #else #set ($primaryTsType = "string") #end +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subColumns = $subColumnsList.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +/** ${subTable.classComment}信息 */ +export interface ${subSimpleClassName} { +#foreach ($column in $subColumns) +#if ($column.primaryKey || $column.createOperation || $column.updateOperation || $column.listOperationResult) +#set ($javaType = $column.javaType.toLowerCase()) +#set ($optional = $column.nullable || $column.primaryKey || ($table.templateType != 11 && $column.id == $subJoinColumn.id)) +#if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") + ${column.javaField}#if($optional)?#end: number +#elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime") + ${column.javaField}#if($optional)?#end: number +#elseif(${javaType} == "boolean") + ${column.javaField}#if($optional)?#end: boolean +#else + ${column.javaField}#if($optional)?#end: string +#end +#end +#end +} + +#end /** ${table.classComment}信息 */ export interface ${simpleClassName} { #foreach ($column in $columns) - #if ($column.primaryKey || $column.createOperation || $column.updateOperation || $column.listOperationResult) - #set ($javaType = $column.javaType.toLowerCase()) - #set ($javaFieldLower = $column.javaField.toLowerCase()) - #set ($optional = $column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime") - #if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") +#if ($column.primaryKey || $column.createOperation || $column.updateOperation || $column.listOperationResult) +#set ($javaType = $column.javaType.toLowerCase()) +#set ($optional = $column.nullable || $column.primaryKey) +#if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") + ${column.javaField}#if($optional)?#end: number +#elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime") ${column.javaField}#if($optional)?#end: number - #elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime") - ${column.javaField}#if($optional)?#end: Date - #elseif(${javaType} == "boolean") +#elseif(${javaType} == "boolean") ${column.javaField}#if($optional)?#end: boolean - #else +#else ${column.javaField}#if($optional)?#end: string - #end - #end +#end +#end +#end +#if ($table.templateType == 2) + children?: ${simpleClassName}[] +#end +#if ($table.templateType == 10 || $table.templateType == 12) +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) + ${subClassNameVar}#if($subTable.subJoinMany)s#end?: ${subSimpleClassName}#if($subTable.subJoinMany)[]#else | null#end +#end #end } +#if ($table.templateType == 2) +/** 获取${table.classComment}列表 */ +export function get${simpleClassName}List(params?: Record) { + return http.get<${simpleClassName}[]>('/${table.moduleName}/${simpleClassName_strikeCase}/list', params) +} +#else /** 获取${table.classComment}分页列表 */ export function get${simpleClassName}Page(params: PageParam) { return http.get>('/${table.moduleName}/${simpleClassName_strikeCase}/page', params) } +#end /** 获取${table.classComment}详情 */ export function get${simpleClassName}(id: ${primaryTsType}) { @@ -39,7 +83,7 @@ export function get${simpleClassName}(id: ${primaryTsType}) { /** 创建${table.classComment} */ export function create${simpleClassName}(data: ${simpleClassName}) { - return http.post('/${table.moduleName}/${simpleClassName_strikeCase}/create', data) + return http.post<${primaryTsType}>('/${table.moduleName}/${simpleClassName_strikeCase}/create', data) } /** 更新${table.classComment} */ @@ -51,3 +95,65 @@ export function update${simpleClassName}(data: ${simpleClassName}) { export function delete${simpleClassName}(id: ${primaryTsType}) { return http.delete(`/${table.moduleName}/${simpleClassName_strikeCase}/delete?id=${id}`) } +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#set ($subPrimaryJavaType = $subPrimaryColumn.javaType.toLowerCase()) +#if(${subPrimaryJavaType} == "long" || ${subPrimaryJavaType} == "integer" || ${subPrimaryJavaType} == "short" || ${subPrimaryJavaType} == "double" || ${subPrimaryJavaType} == "bigdecimal" || ${subPrimaryJavaType} == "byte") +#set ($subPrimaryTsType = "number") +#else +#set ($subPrimaryTsType = "string") +#end +#set ($subJoinJavaType = $subJoinColumn.javaType.toLowerCase()) +#if(${subJoinJavaType} == "long" || ${subJoinJavaType} == "integer" || ${subJoinJavaType} == "short" || ${subJoinJavaType} == "double" || ${subJoinJavaType} == "bigdecimal" || ${subJoinJavaType} == "byte") +#set ($subJoinTsType = "number") +#else +#set ($subJoinTsType = "string") +#end +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + $subJoinColumn.javaField.substring(1)) +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index)) +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) + +// ==================== 子表:${subTable.classComment} ==================== +#if ($table.templateType == 11) + +/** 获取${subTable.classComment}分页列表 */ +export function get${subSimpleClassName}Page(params: PageParam & { ${subJoinColumn.javaField}: ${subJoinTsType} }) { + return http.get>('/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/page', params) +} + +/** 获取${subTable.classComment}详情 */ +export function get${subSimpleClassName}(id: ${subPrimaryTsType}) { + return http.get<${subSimpleClassName}>(`/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/get?id=${id}`) +} + +/** 创建${subTable.classComment} */ +export function create${subSimpleClassName}(data: ${subSimpleClassName}) { + return http.post<${subPrimaryTsType}>('/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/create', data) +} + +/** 更新${subTable.classComment} */ +export function update${subSimpleClassName}(data: ${subSimpleClassName}) { + return http.put('/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/update', data) +} + +/** 删除${subTable.classComment} */ +export function delete${subSimpleClassName}(id: ${subPrimaryTsType}) { + return http.delete(`/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/delete?id=${id}`) +} +#elseif ($subTable.subJoinMany) + +/** 获取${subTable.classComment}列表 */ +export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: ${subJoinTsType}) { + return http.get<${subSimpleClassName}[]>(`/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=#[[${]]#${subJoinColumn.javaField}#[[}]]#`) +} +#else + +/** 获取${subTable.classComment} */ +export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: ${subJoinTsType}) { + return http.get<${subSimpleClassName} | null>(`/${table.moduleName}/${simpleClassName_strikeCase}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=#[[${]]#${subJoinColumn.javaField}#[[}]]#`) +} +#end +#end diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/components/breadcrumb_tree.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/components/breadcrumb_tree.vue.vm new file mode 100644 index 0000000..e79d65a --- /dev/null +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/components/breadcrumb_tree.vue.vm @@ -0,0 +1,87 @@ + + + diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail/index.vue.vm index bde41c2..c861eea 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail/index.vue.vm @@ -39,7 +39,7 @@ 删除 @@ -49,6 +49,12 @@ diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_master.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_master.vue.vm new file mode 100644 index 0000000..1499a8d --- /dev/null +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/detail_master.vue.vm @@ -0,0 +1,239 @@ + + + diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form/index.vue.vm index 6c13045..84798e8 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form/index.vue.vm @@ -12,21 +12,31 @@ #foreach($column in $columns) - #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey) - #set ($dictType = $column.dictType) - #set ($javaField = $column.javaField) - #set ($javaType = $column.javaType) - #set ($comment = $column.columnComment) - #set ($dictMethod = "getDictOptions") - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") - #set ($dictMethod = "getIntDictOptions") - #elseif ($javaType == "String") - #set ($dictMethod = "getStrDictOptions") - #elseif ($javaType == "Boolean") - #set ($dictMethod = "getBoolDictOptions") - #end - ## 下拉选择(字典)→ yd-form-picker,内部按 dictType 解析选项,适合选项较多 - #if ($column.htmlType == "select" && $dictType && "" != $dictType) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey) +#set ($dictType = $column.dictType) +#set ($javaField = $column.javaField) +#set ($javaType = $column.javaType) +#set ($comment = $column.columnComment) +#set ($dictMethod = "getDictOptions") +#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") +#set ($dictMethod = "getIntDictOptions") +#elseif ($javaType == "String") +#set ($dictMethod = "getStrDictOptions") +#elseif ($javaType == "Boolean") +#set ($dictMethod = "getBoolDictOptions") +#end +## 树表的父级选择 +#if ($table.templateType == 2 && $column.id == $treeParentColumn.id) + +## 下拉选择(字典)→ yd-form-picker,内部按 dictType 解析选项,适合选项较多 +#elseif ($column.htmlType == "select" && $dictType && "" != $dictType) - ## 单选(字典)→ radio-group,适合选项较少 - #elseif ($column.htmlType == "radio" && $dictType && "" != $dictType) +## 单选(字典)→ radio-group,适合选项较少 +#elseif ($column.htmlType == "radio" && $dictType && "" != $dictType) - ## 数字类型(无字典) - #elseif (${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer" || ${javaType.toLowerCase()} == "short" || ${javaType.toLowerCase()} == "double" || ${javaType.toLowerCase()} == "bigdecimal" || ${javaType.toLowerCase()} == "byte") +## 数字类型(无字典) +#elseif (${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer" || ${javaType.toLowerCase()} == "short" || ${javaType.toLowerCase()} == "double" || ${javaType.toLowerCase()} == "bigdecimal" || ${javaType.toLowerCase()} == "byte") - ## 布尔类型 - #elseif (${javaType.toLowerCase()} == "boolean") +## 布尔类型 +#elseif (${javaType.toLowerCase()} == "boolean") - ## 日期时间类型 - #elseif (${javaType.toLowerCase()} == "date" || ${javaType.toLowerCase()} == "localdate" || ${javaType.toLowerCase()} == "localdatetime") - #set ($pickerType = "date") - #if (${javaType.toLowerCase()} == "localdatetime") - #set ($pickerType = "datetime") - #end +## 日期时间类型 +#elseif (${javaType.toLowerCase()} == "date" || ${javaType.toLowerCase()} == "localdate" || ${javaType.toLowerCase()} == "localdatetime") +#set ($pickerType = "date") +#if (${javaType.toLowerCase()} == "localdatetime") +#set ($pickerType = "datetime") +#end - ## 文本域 - #elseif ($column.htmlType == "textarea") +## 文本域 +#elseif ($column.htmlType == "textarea") - ## 图片上传 → yd-upload-img(包 wd-form-item 才能注册到 wd-form 做校验/错误展示) - #elseif ($column.htmlType == "imageUpload") +## 图片上传 → yd-upload-img(包 wd-form-item 才能注册到 wd-form 做校验/错误展示) +#elseif ($column.htmlType == "imageUpload") - ## 文件上传 → yd-upload-file - #elseif ($column.htmlType == "fileUpload") +## 文件上传 → yd-upload-file +#elseif ($column.htmlType == "fileUpload") - ## 默认:文本输入 - #else +## 默认:文本输入 +#else - #end - #end +#end +#end #end +#if ($table.templateType == 10 || $table.templateType == 12) +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subColumns = $subColumnsList.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) + + + + ${subTable.classComment} +#if ($subTable.subJoinMany) + + 添加 + +#else + + 添加 + +#end + + +#if ($subTable.subJoinMany) + + 暂无${subTable.classComment} + + + + + 删除 + + +#foreach ($column in $subColumns) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && $column.id != $subJoinColumn.id) +#set ($javaType = $column.javaType.toLowerCase()) +#set ($dictMethod = "getDictOptions") +#if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short") +#set ($dictMethod = "getIntDictOptions") +#elseif ($column.javaType == "String") +#set ($dictMethod = "getStrDictOptions") +#elseif ($column.javaType == "Boolean") +#set ($dictMethod = "getBoolDictOptions") +#end +#if ($column.htmlType == "select" && $column.dictType && "" != $column.dictType) + +#elseif ($column.htmlType == "radio" && $column.dictType && "" != $column.dictType) + + + + {{ dict.label }} + + + +#elseif ($javaType == "boolean") + + + +#elseif ($javaType == "long" || $javaType == "integer" || $javaType == "short" || $javaType == "double" || $javaType == "bigdecimal" || $javaType == "byte") + + + +#elseif ($javaType == "date" || $javaType == "localdate" || $javaType == "localdatetime") +#set ($subPickerType = "date") +#if ($javaType == "localdatetime") +#set ($subPickerType = "datetime") +#end + + +#elseif ($column.htmlType == "textarea") + + + +#elseif ($column.htmlType == "imageUpload") + + + +#elseif ($column.htmlType == "fileUpload") + + + +#else + + + +#end +#end +#end + +#else + + 暂无${subTable.classComment} + + +#foreach ($column in $subColumns) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && $column.id != $subJoinColumn.id) +#set ($javaType = $column.javaType.toLowerCase()) +#set ($dictMethod = "getDictOptions") +#if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short") +#set ($dictMethod = "getIntDictOptions") +#elseif ($column.javaType == "String") +#set ($dictMethod = "getStrDictOptions") +#elseif ($column.javaType == "Boolean") +#set ($dictMethod = "getBoolDictOptions") +#end +#if ($column.htmlType == "select" && $column.dictType && "" != $column.dictType) + +#elseif ($column.htmlType == "radio" && $column.dictType && "" != $column.dictType) + + + + {{ dict.label }} + + + +#elseif ($javaType == "boolean") + + + +#elseif ($javaType == "long" || $javaType == "integer" || $javaType == "short" || $javaType == "double" || $javaType == "bigdecimal" || $javaType == "byte") + + + +#elseif ($javaType == "date" || $javaType == "localdate" || $javaType == "localdatetime") +#set ($subPickerType = "date") +#if ($javaType == "localdatetime") +#set ($subPickerType = "datetime") +#end + + +#elseif ($column.htmlType == "textarea") + + + +#elseif ($column.htmlType == "imageUpload") + + + +#elseif ($column.htmlType == "fileUpload") + + + +#else + + + +#end +#end +#end + +#end + +#end +#end @@ -154,54 +420,113 @@ import type { FormInstance } from '@wot-ui/ui/components/wd-form/types' #set ($hasDict = 0) #set ($hasDate = 0) #set ($hasDateTime = 0) +#set ($hasSubDate = 0) #set ($hasGetDictOptions = 0) #set ($hasGetIntDictOptions = 0) #set ($hasGetStrDictOptions = 0) #set ($hasGetBoolDictOptions = 0) #foreach ($column in $columns) - #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && ($column.htmlType == "select" || $column.htmlType == "radio") && $column.dictType && "" != $column.dictType) - #set ($hasDict = 1) - #if ($column.htmlType == "radio" && ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")) - #set ($hasGetIntDictOptions = 1) - #elseif ($column.htmlType == "radio" && $column.javaType == "String") - #set ($hasGetStrDictOptions = 1) - #elseif ($column.htmlType == "radio" && $column.javaType == "Boolean") - #set ($hasGetBoolDictOptions = 1) - #elseif ($column.htmlType == "radio") - #set ($hasGetDictOptions = 1) - #end - #end - #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey +#set ($hasDict = 1) +#if ($column.htmlType == "radio" && ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")) +#set ($hasGetIntDictOptions = 1) +#elseif ($column.htmlType == "radio" && $column.javaType == "String") +#set ($hasGetStrDictOptions = 1) +#elseif ($column.htmlType == "radio" && $column.javaType == "Boolean") +#set ($hasGetBoolDictOptions = 1) +#elseif ($column.htmlType == "radio") +#set ($hasGetDictOptions = 1) +#end +#end +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate")) - #set ($hasDate = 1) - #end - #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey +#set ($hasDate = 1) +#end +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && ${column.javaType.toLowerCase()} == "localdatetime") - #set ($hasDateTime = 1) - #end +#set ($hasDateTime = 1) #end -import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' +#end +#if ($table.templateType == 10 || $table.templateType == 12) +#foreach ($subColumns in $subColumnsList) +#foreach ($column in $subColumns) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey + && ($column.htmlType == "select" || $column.htmlType == "radio") + && $column.dictType && "" != $column.dictType) +#set ($hasDict = 1) +#if ($column.htmlType == "radio" && ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")) +#set ($hasGetIntDictOptions = 1) +#elseif ($column.htmlType == "radio" && $column.javaType == "String") +#set ($hasGetStrDictOptions = 1) +#elseif ($column.htmlType == "radio" && $column.javaType == "Boolean") +#set ($hasGetBoolDictOptions = 1) +#elseif ($column.htmlType == "radio") +#set ($hasGetDictOptions = 1) +#end +#end +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey + && (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate")) +#set ($hasDate = 1) +#set ($hasSubDate = 1) +#end +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey + && ${column.javaType.toLowerCase()} == "localdatetime") +#set ($hasDateTime = 1) +#set ($hasSubDate = 1) +#end +#end +#end +#end +import type { + ${simpleClassName}, +#if ($table.templateType == 10 || $table.templateType == 12) +#foreach ($subSimpleClassName in $subSimpleClassNames) + ${subSimpleClassName}, +#end +#end +} from '@/api/${table.moduleName}/${table.businessName}' import { computed, onMounted, ref } from 'vue' import { useToast } from '@wot-ui/ui/components/wd-toast' +#if ($table.templateType == 10 || $table.templateType == 12) +import { + create${simpleClassName}, + get${simpleClassName}, +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + $subJoinColumn.javaField.substring(1)) +#if ($subTable.subJoinMany) + get${subSimpleClassName}ListBy${SubJoinColumnName}, +#else + get${subSimpleClassName}By${SubJoinColumnName}, +#end +#end + update${simpleClassName}, +} from '@/api/${table.moduleName}/${table.businessName}' +#elseif ($table.templateType == 2) +import { create${simpleClassName}, get${simpleClassName}, get${simpleClassName}List, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' +#else import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}' +#end #if ($hasGetDictOptions == 1 || $hasGetIntDictOptions == 1 || $hasGetStrDictOptions == 1 || $hasGetBoolDictOptions == 1) - #set ($dictImportNames = "") - #if ($hasGetDictOptions == 1) - #set ($dictImportNames = "${dictImportNames}getDictOptions, ") - #end - #if ($hasGetIntDictOptions == 1) - #set ($dictImportNames = "${dictImportNames}getIntDictOptions, ") - #end - #if ($hasGetStrDictOptions == 1) - #set ($dictImportNames = "${dictImportNames}getStrDictOptions, ") - #end - #if ($hasGetBoolDictOptions == 1) - #set ($dictImportNames = "${dictImportNames}getBoolDictOptions, ") - #end - #set ($dictImportNames = $dictImportNames.trim()) - #set ($dictImportNames = $dictImportNames.substring(0, $dictImportNames.length() - 1)) +#set ($dictImportNames = "") +#if ($hasGetDictOptions == 1) +#set ($dictImportNames = "${dictImportNames}getDictOptions, ") +#end +#if ($hasGetIntDictOptions == 1) +#set ($dictImportNames = "${dictImportNames}getIntDictOptions, ") +#end +#if ($hasGetStrDictOptions == 1) +#set ($dictImportNames = "${dictImportNames}getStrDictOptions, ") +#end +#if ($hasGetBoolDictOptions == 1) +#set ($dictImportNames = "${dictImportNames}getBoolDictOptions, ") +#end +#set ($dictImportNames = $dictImportNames.trim()) +#set ($dictImportNames = $dictImportNames.substring(0, $dictImportNames.length() - 1)) import { $dictImportNames } from '@/hooks/useDict' #end import { delay, navigateBackPlus } from '@/utils' @@ -209,21 +534,27 @@ import { delay, navigateBackPlus } from '@/utils' import { DICT_TYPE } from '@/utils/constants' #end #if ($hasDate == 1 || $hasDateTime == 1) - #set ($dateImportNames = "") - #if ($hasDate == 1) - #set ($dateImportNames = "${dateImportNames}formatDate, ") - #end - #if ($hasDateTime == 1) - #set ($dateImportNames = "${dateImportNames}formatDateTime, ") - #end - #set ($dateImportNames = $dateImportNames.trim()) - #set ($dateImportNames = $dateImportNames.substring(0, $dateImportNames.length() - 1)) +#set ($dateImportNames = "") +#if ($hasDate == 1) +#set ($dateImportNames = "${dateImportNames}formatDate, ") +#end +#if ($hasDateTime == 1) +#set ($dateImportNames = "${dateImportNames}formatDateTime, ") +#end +#set ($dateImportNames = $dateImportNames.trim()) +#set ($dateImportNames = $dateImportNames.substring(0, $dateImportNames.length() - 1)) import { $dateImportNames } from '@/utils/date' #end import { createFormSchema } from '@/utils/wot' +#if ($table.templateType == 2) +import { handleTree } from '@/utils/tree' +#end const props = defineProps<{ - id?: ${primaryTsType} | any + id?: ${primaryTsType} +#if ($table.templateType == 2) + ${treeParentColumn.javaField}?: ${primaryTsType} +#end }>() definePage({ @@ -238,40 +569,153 @@ const getTitle = computed(() => props.id ? '编辑${table.classComment}' : '新å const formLoading = ref(false) // 表单提交状态 const formData = ref<${simpleClassName}>({ #foreach($column in $columns) - #if (($column.createOperation || $column.updateOperation) || $column.primaryKey) - #set ($javaType = $column.javaType.toLowerCase()) - #set ($javaFieldLower = $column.javaField.toLowerCase()) - #set ($optional = $column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime") - #if ($column.primaryKey) +#if (($column.createOperation || $column.updateOperation) || $column.primaryKey) +#set ($javaType = $column.javaType.toLowerCase()) +#set ($javaFieldLower = $column.javaField.toLowerCase()) +#set ($optional = $column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime") +#if ($column.primaryKey) ${column.javaField}: undefined, - #elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") +#elseif($table.templateType == 2 && $column.id == $treeParentColumn.id) + ${column.javaField}: props.${column.javaField} ?? 0, +#elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte") +#if($column.nullable) + ${column.javaField}: undefined, +#else ${column.javaField}: 0, - #elseif(${javaType} == "boolean") +#end +#elseif(${javaType} == "boolean") ${column.javaField}: false, - #elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime") - ${column.javaField}: undefined, - #else +#elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime") + ${column.javaField}:#if($column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime") undefined#else 0#end, +#else ${column.javaField}: '', - #end - #end +#end +#end #end }) // 表单数据 +#if ($table.templateType == 10 || $table.templateType == 12) +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) +#set ($subColumns = $subColumnsList.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#if ($subTable.subJoinMany) +const ${subClassNameVar}s = ref<${subSimpleClassName}[]>([]) // ${subTable.classComment}数据 +#else +const ${subClassNameVar} = ref<${subSimpleClassName} | null>(null) // ${subTable.classComment}数据 +#end +#end +#end #foreach($column in $columns) - #if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")) const ${column.javaField}Visible = ref(false) // ${column.columnComment}选择器状态 - #end +#end +#end +#if ($hasSubDate == 1) +const subDateVisible = ref>({}) // 子表日期选择器状态 #end const formSchema = createFormSchema({ #foreach($column in $columns) - #set ($javaFieldLower = $column.javaField.toLowerCase()) - #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey +#set ($javaFieldLower = $column.javaField.toLowerCase()) +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $javaFieldLower != "createtime" && $javaFieldLower != "updatetime") ${column.javaField}: [{ required: true, message: '${column.columnComment}不能为空' }], - #end +#end #end }) // 表单校验规则 const formRef = ref() // 表单组件引用 +#if ($table.templateType == 2) +const treeData = ref<${simpleClassName}[]>([]) // 父级树形选项 +#end + +#if ($table.templateType == 10 || $table.templateType == 12) +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) +#set ($subColumns = $subColumnsList.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#if ($subTable.subJoinMany) +#set ($subClassNameVar = $subClassNameVars.get($index)) +#set ($subColumns = $subColumnsList.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +/** 添加${subTable.classComment} */ +function add${subClassNameVar.substring(0,1).toUpperCase()}${subClassNameVar.substring(1)}() { + ${subClassNameVar}s.value.push({ +#foreach ($column in $subColumns) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && $column.id != $subJoinColumn.id) +#set ($javaType = $column.javaType.toLowerCase()) + ${column.javaField}:#if($column.nullable) undefined#elseif($javaType == "long" || $javaType == "integer" || $javaType == "short" || $javaType == "double" || $javaType == "bigdecimal" || $javaType == "byte" || $javaType == "date" || $javaType == "localdate" || $javaType == "localdatetime") 0#elseif($javaType == "boolean") false#else ''#end, +#end +#end + }) +} +/** 删除${subTable.classComment} */ +function remove${subClassNameVar.substring(0,1).toUpperCase()}${subClassNameVar.substring(1)}(index: number) { + ${subClassNameVar}s.value.splice(index, 1) +} + +#else +/** 添加${subTable.classComment} */ +function add${subClassNameVar.substring(0,1).toUpperCase()}${subClassNameVar.substring(1)}() { + ${subClassNameVar}.value = { +#foreach ($column in $subColumns) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && $column.id != $subJoinColumn.id) +#set ($javaType = $column.javaType.toLowerCase()) + ${column.javaField}:#if($column.nullable) undefined#elseif($javaType == "long" || $javaType == "integer" || $javaType == "short" || $javaType == "double" || $javaType == "bigdecimal" || $javaType == "byte" || $javaType == "date" || $javaType == "localdate" || $javaType == "localdatetime") 0#elseif($javaType == "boolean") false#else ''#end, +#end +#end + } +} + +#end +#end +/** 校验主子表数据 */ +function isEmptySubValue(value: unknown) { + return value === undefined || value === null || value === '' +} + +function validateSubTables() { +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subClassNameVar = $subClassNameVars.get($index)) +#set ($subColumns = $subColumnsList.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#if ($subTable.subJoinMany) + for (let index = 0; index < ${subClassNameVar}s.value.length; index++) { + const item = ${subClassNameVar}s.value[index]! +#foreach ($column in $subColumns) +#set ($javaFieldLower = $column.javaField.toLowerCase()) +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey + && $column.id != $subJoinColumn.id && $javaFieldLower != "createtime" && $javaFieldLower != "updatetime") + if (isEmptySubValue(item.${column.javaField})) { + toast.warning(`${subTable.classComment}第#[[${]]#index + 1#[[}]]#项的${column.columnComment}不能为空`) + return false + } +#end +#end + } +#else + if (${subClassNameVar}.value) { +#foreach ($column in $subColumns) +#set ($javaFieldLower = $column.javaField.toLowerCase()) +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey + && $column.id != $subJoinColumn.id && $javaFieldLower != "createtime" && $javaFieldLower != "updatetime") + if (isEmptySubValue(${subClassNameVar}.value.${column.javaField})) { + toast.warning('${subTable.classComment}的${column.columnComment}不能为空') + return false + } +#end +#end + } +#end +#end + return true +} + +#end /** 返回上一页 */ function handleBack() { navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index') @@ -282,7 +726,34 @@ async function getDetail() { if (!props.id) { return } +#if ($table.templateType == 10 || $table.templateType == 12) + const [data#foreach ($subTable in $subTables)#set ($index = $foreach.count - 1), ${subClassNameVars.get($index)}Data#end] = await Promise.all([ + get${simpleClassName}(props.id), +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index)) +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + $subJoinColumn.javaField.substring(1)) +#if ($subTable.subJoinMany) + get${subSimpleClassName}ListBy${SubJoinColumnName}(props.id), +#else + get${subSimpleClassName}By${SubJoinColumnName}(props.id), +#end +#end + ]) + formData.value = data +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subClassNameVar = $subClassNameVars.get($index)) +#if ($subTable.subJoinMany) + ${subClassNameVar}s.value = ${subClassNameVar}Data || [] +#else + ${subClassNameVar}.value = ${subClassNameVar}Data || null +#end +#end +#else formData.value = await get${simpleClassName}(props.id) +#end } /** 提交表单 */ @@ -291,14 +762,31 @@ async function handleSubmit() { if (!valid) { return } +#if ($table.templateType == 10 || $table.templateType == 12) + if (!validateSubTables()) { + return + } +#end formLoading.value = true try { +#if ($table.templateType == 10 || $table.templateType == 12) + const data: ${simpleClassName} = { + ...formData.value, +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subClassNameVar = $subClassNameVars.get($index)) + ${subClassNameVar}#if($subTable.subJoinMany)s#end: ${subClassNameVar}#if($subTable.subJoinMany)s#end.value, +#end + } +#else + const data = formData.value +#end if (props.id) { - await update${simpleClassName}(formData.value) + await update${simpleClassName}(data) toast.success('修改成功') } else { - await create${simpleClassName}(formData.value) + await create${simpleClassName}(data) toast.success('新增成功') } uni.$emit('${table.moduleName}:${table.businessName}:reload') @@ -309,7 +797,16 @@ async function handleSubmit() { } /** 初始化 */ -onMounted(() => { +onMounted(async () => { +#if ($table.templateType == 2) + const data = await get${simpleClassName}List() + treeData.value = [{ + ${primaryColumn.javaField}: 0, + ${treeNameColumn.javaField}: '顶级${table.classComment}', + ${treeParentColumn.javaField}: 0, + children: handleTree(data, '${primaryColumn.javaField}', '${treeParentColumn.javaField}'), + } as ${simpleClassName}] +#end getDetail() }) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form_sub_erp.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form_sub_erp.vue.vm new file mode 100644 index 0000000..46560d5 --- /dev/null +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/form_sub_erp.vue.vm @@ -0,0 +1,227 @@ +#set ($subTable = $subTables.get($subIndex)) +#set ($subColumns = $subColumnsList.get($subIndex)) +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex)) +#set ($subPrimaryJavaType = $subPrimaryColumn.javaType.toLowerCase()) +#if(${subPrimaryJavaType} == "long" || ${subPrimaryJavaType} == "integer" || ${subPrimaryJavaType} == "short" || ${subPrimaryJavaType} == "double" || ${subPrimaryJavaType} == "bigdecimal" || ${subPrimaryJavaType} == "byte") +#set ($subPrimaryTsType = "number") +#else +#set ($subPrimaryTsType = "string") +#end +#set ($subJoinJavaType = $subJoinColumn.javaType.toLowerCase()) +#if(${subJoinJavaType} == "long" || ${subJoinJavaType} == "integer" || ${subJoinJavaType} == "short" || ${subJoinJavaType} == "double" || ${subJoinJavaType} == "bigdecimal" || ${subJoinJavaType} == "byte") +#set ($subJoinTsType = "number") +#else +#set ($subJoinTsType = "string") +#end +#set ($hasDict = 0) +#set ($hasDate = 0) +#set ($hasDateTime = 0) +#foreach ($column in $subColumns) +#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey && $column.id != $subJoinColumn.id) +#if (($column.htmlType == "select" || $column.htmlType == "radio") && $column.dictType && "" != $column.dictType) +#set ($hasDict = 1) +#end +#if (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate") +#set ($hasDate = 1) +#end +#if (${column.javaType.toLowerCase()} == "localdatetime") +#set ($hasDateTime = 1) +#end +#end +#end + + + diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/index_tree.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/index_tree.vue.vm new file mode 100644 index 0000000..4686fd7 --- /dev/null +++ b/yudao-module-infra/src/main/resources/codegen/vue3_admin_uniapp/views/index_tree.vue.vm @@ -0,0 +1,151 @@ + + + diff --git a/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java b/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java index ba0850a..3dee985 100644 --- a/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java +++ b/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java @@ -157,13 +157,17 @@ public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest { String lastFilePath = StrUtil.subAfter(filePath, '/', true); String ext = StrUtil.subAfter(lastFilePath, '.', true); String name = StrUtil.subBefore(lastFilePath, '.', true); - String contentPath = ext + '/' + name; - // 同名文件(如 index.vue 同时出现在 列表/form/detail)会撞名,撞名时前缀补上级目录区分;仍撞则加序号兜底,避免快照互相覆盖 + String parentPath = StrUtil.subBefore(filePath, '/' + lastFilePath, true); + String parentDir = StrUtil.subAfter(parentPath, '/', true); + // index.vue 按页面语义稳定归档,避免结果迭代顺序导致列表页和表单页的快照路径互换 + String contentPath = "index".equals(name) && ("form".equals(parentDir) || "detail".equals(parentDir)) + ? ext + '/' + parentDir + '/' + name : ext + '/' + name; + // ERP 多个子表的 form/index.vue 仍可能撞名,继续补充祖父目录区分 if (usedContentPaths.contains(contentPath)) { - String parentDir = StrUtil.subAfter(StrUtil.subBefore(filePath, '/' + lastFilePath, true), '/', true); - contentPath = ext + '/' + parentDir + '/' + name; + String grandParentDir = StrUtil.subAfter(StrUtil.subBefore(parentPath, '/' + parentDir, true), '/', true); + contentPath = ext + '/' + grandParentDir + '/' + parentDir + '/' + name; for (int i = 2; usedContentPaths.contains(contentPath); i++) { - contentPath = ext + '/' + parentDir + '/' + name + '-' + i; + contentPath = ext + '/' + grandParentDir + '/' + parentDir + '/' + name + '-' + i; } } usedContentPaths.add(contentPath); diff --git a/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineUniappTest.java b/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineUniappTest.java index 958afe2..583a4f6 100644 --- a/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineUniappTest.java +++ b/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineUniappTest.java @@ -7,10 +7,13 @@ import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; import com.baomidou.mybatisplus.annotation.DbType; import org.junit.jupiter.api.Test; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -59,4 +62,182 @@ public class CodegenEngineUniappTest extends CodegenEngineAbstractTest { assertTrue(searchForm.contains("sex: undefined as string | undefined,")); } + @Test + public void testExecute_tree() { + // 准备参数 + CodegenTableDO table = getTable("category") + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); + List columns = getColumnList("category"); + + // 调用 + Map result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); + // 断言 + assertResult(result, "/vue3_admin_uniapp_tree"); + } + + @Test + public void testExecute_semantics() { + // 准备参数 + CodegenTableDO table = getTable("student") + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); + List columns = getColumnList("student"); + + // 调用 + Map result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); + // 断言 + String api = result.get("yudao-ui-admin-uniapp/src/api/infra/demo/index.ts"); + assertTrue(api.contains("birthday: number")); + assertTrue(api.contains("createTime?: number")); + assertFalse(api.contains("createTime?: Date")); + String detail = result.get("yudao-ui-admin-uniapp/src/pages-infra/demo/detail/index.vue"); + assertTrue(detail.contains("type=\"danger\"")); + assertFalse(detail.contains("type=\"error\"")); + } + + @Test + public void testExecute_stringPrimaryKey() { + // 准备主表 + CodegenTableDO table = getTable("student") + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setTemplateType(CodegenTemplateTypeEnum.MASTER_ERP.getType()); + List columns = getColumnList("student"); + columns.stream().filter(CodegenColumnDO::getPrimaryKey).findFirst().orElseThrow().setJavaType("String"); + // 准备子表 + CodegenTableDO contactTable = getTable("contact") + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setSubJoinColumnId(100L).setSubJoinMany(true); + List contactColumns = getColumnList("contact"); + contactColumns.stream().filter(CodegenColumnDO::getPrimaryKey).findFirst().orElseThrow().setJavaType("String"); + contactColumns.stream().filter(column -> Objects.equals(column.getId(), 100L)) + .findFirst().orElseThrow().setJavaType("String"); + + // 调用 + Map result = codegenEngine.execute(DbType.MYSQL, table, columns, + List.of(contactTable), List.of(contactColumns)); + // 断言 + String api = result.get("yudao-ui-admin-uniapp/src/api/infra/demo/index.ts"); + assertTrue(api.contains("return http.post('/infra/student/create', data)")); + assertTrue(api.contains("studentId: string")); + assertTrue(api.contains("getStudentContact(id: string)")); + assertTrue(api.contains("deleteStudentContact(id: string)")); + String detail = result.get("yudao-ui-admin-uniapp/src/pages-infra/demo/detail/index.vue"); + assertFalse(detail.contains("Number(props.id)")); + String subForm = result.get("yudao-ui-admin-uniapp/src/pages-infra/demo/student-contact/form/index.vue"); + assertTrue(subForm.contains("id?: string")); + assertTrue(subForm.contains("studentId: string")); + } + + @Test + public void testExecute_treeSearch() { + // 准备参数 + CodegenTableDO table = getTable("category") + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); + List columns = getColumnList("category"); + + // 调用 + Map result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); + // 断言 + String index = result.get("yudao-ui-admin-uniapp/src/pages-infra/demo/index.vue"); + assertTrue(index.contains("currentParentId.value === 0\n ? list.value")); + assertFalse(index.contains("list.value.filter")); + String breadcrumb = result.get("yudao-ui-admin-uniapp/src/pages-infra/demo/components/breadcrumb.vue"); + assertTrue(breadcrumb.contains("modelValue: number")); + assertFalse(breadcrumb.contains("TreeValue")); + } + + @Test + public void testExecute_duplicateSubPath() { + // 准备主表 + CodegenTableDO table = getTable("student") + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setTemplateType(CodegenTemplateTypeEnum.MASTER_ERP.getType()); + List columns = getColumnList("student"); + // 准备两个归一化名称相同的子表 + CodegenTableDO crmItemTable = getTable("contact").setModuleName("crm").setClassName("CrmOrderItem") + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setSubJoinColumnId(100L).setSubJoinMany(true); + CodegenTableDO erpItemTable = getTable("contact").setModuleName("erp").setClassName("ErpOrderItem") + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setSubJoinColumnId(100L).setSubJoinMany(true); + List crmItemColumns = getColumnList("contact"); + List erpItemColumns = getColumnList("contact"); + + // 调用 + IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> codegenEngine.execute(DbType.MYSQL, table, columns, + Arrays.asList(crmItemTable, erpItemTable), Arrays.asList(crmItemColumns, erpItemColumns))); + // 断言 + assertTrue(exception.getMessage().contains("生成文件路径重复")); + assertTrue(exception.getMessage().contains("subIndex=0")); + assertTrue(exception.getMessage().contains("subIndex=1")); + } + + @Test + public void testExecute_masterNormal() { + testExecute_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "/vue3_admin_uniapp_master_normal"); + } + + @Test + public void testExecute_masterInner() { + testExecute_master(CodegenTemplateTypeEnum.MASTER_INNER, "/vue3_admin_uniapp_master_inner"); + } + + @Test + public void testExecute_masterErp() { + testExecute_master(CodegenTemplateTypeEnum.MASTER_ERP, "/vue3_admin_uniapp_master_erp"); + } + + private void testExecute_master(CodegenTemplateTypeEnum templateType, String path) { + // 准备主表 + CodegenTableDO table = getTable("student") + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setTemplateType(templateType.getType()); + List columns = getColumnList("student"); + // 准备一对多子表 + CodegenTableDO contactTable = getTable("contact") + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setSubJoinColumnId(100L).setSubJoinMany(true); + List contactColumns = getColumnList("contact"); + // 准备一对一子表 + CodegenTableDO teacherTable = getTable("teacher") + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()) + .setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) + .setSubJoinColumnId(200L).setSubJoinMany(false); + List teacherColumns = getColumnList("teacher"); + + // 调用 + Map result = codegenEngine.execute(DbType.MYSQL, table, columns, + Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns)); + // 断言 + assertResult(result, path); + if (templateType != CodegenTemplateTypeEnum.MASTER_ERP) { + String api = result.get("yudao-ui-admin-uniapp/src/api/infra/demo/index.ts"); + assertTrue(api.contains("studentTeacher?: StudentTeacher | null")); + String form = result.get("yudao-ui-admin-uniapp/src/pages-infra/demo/form/index.vue"); + assertTrue(form.contains("ref(null)")); + assertTrue(form.contains("studentTeacher.value = studentTeacherData || null")); + assertTrue(form.contains(":model-value=\"item.birthday || Date.now()\"")); + assertTrue(form.contains("v-model=\"item.sex\"")); + assertTrue(form.contains(" { + + default PageResult selectPage(PageParam reqVO, Long studentId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(InfraStudentContactDO::getStudentId, studentId) + .orderByDesc(InfraStudentContactDO::getId)); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentIds(List studentIds) { + return deleteBatch(InfraStudentContactDO::getStudentId, studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentController b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentController new file mode 100644 index 0000000..02bd597 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentController @@ -0,0 +1,210 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除学生") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentList(@RequestParam("ids") List ids) { + studentService.deleteStudentListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/page") + @Operation(summary = "获得学生联系人分页") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactPage(PageParam pageReqVO, + @RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactPage(pageReqVO, studentId)); + } + + @PostMapping("/student-contact/create") + @Operation(summary = "创建学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) { + return success(studentService.createStudentContact(studentContact)); + } + + @PutMapping("/student-contact/update") + @Operation(summary = "更新学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) { + studentService.updateStudentContact(studentContact); + return success(true); + } + + @DeleteMapping("/student-contact/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentContact(@RequestParam("id") Long id) { + studentService.deleteStudentContact(id); + return success(true); + } + + @DeleteMapping("/student-contact/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentContactList(@RequestParam("ids") List ids) { + studentService.deleteStudentContactListByIds(ids); + return success(true); + } + + @GetMapping("/student-contact/get") + @Operation(summary = "获得学生联系人") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentContact(@RequestParam("id") Long id) { + return success(studentService.getStudentContact(id)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/page") + @Operation(summary = "获得学生班主任分页") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentTeacherPage(PageParam pageReqVO, + @RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherPage(pageReqVO, studentId)); + } + + @PostMapping("/student-teacher/create") + @Operation(summary = "创建学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) { + return success(studentService.createStudentTeacher(studentTeacher)); + } + + @PutMapping("/student-teacher/update") + @Operation(summary = "更新学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) { + studentService.updateStudentTeacher(studentTeacher); + return success(true); + } + + @DeleteMapping("/student-teacher/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentTeacher(@RequestParam("id") Long id) { + studentService.deleteStudentTeacher(id); + return success(true); + } + + @DeleteMapping("/student-teacher/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentTeacherList(@RequestParam("ids") List ids) { + studentService.deleteStudentTeacherListByIds(ids); + return success(true); + } + + @GetMapping("/student-teacher/get") + @Operation(summary = "获得学生班主任") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacher(@RequestParam("id") Long id) { + return success(studentService.getStudentTeacher(id)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentDO new file mode 100644 index 0000000..f39fef2 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentDO @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentMapper new file mode 100644 index 0000000..34e70a0 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentPageReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentPageReqVO new file mode 100644 index 0000000..52d7a23 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentPageReqVO @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO new file mode 100644 index 0000000..12166f4 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.idev.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentSaveReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentSaveReqVO new file mode 100644 index 0000000..2378872 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentSaveReqVO @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentService b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentService new file mode 100644 index 0000000..fea24fa --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentService @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 批量删除学生 + * + * @param ids 编号 + */ + void deleteStudentListByIds(List ids); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人分页 + * + * @param pageReqVO 分页查询 + * @param studentId 学生编号 + * @return 学生联系人分页 + */ + PageResult getStudentContactPage(PageParam pageReqVO, Long studentId); + + /** + * 创建学生联系人 + * + * @param studentContact 创建信息 + * @return 编号 + */ + Long createStudentContact(@Valid InfraStudentContactDO studentContact); + + /** + * 更新学生联系人 + * + * @param studentContact 更新信息 + */ + void updateStudentContact(@Valid InfraStudentContactDO studentContact); + + /** + * 删除学生联系人 + * + * @param id 编号 + */ + void deleteStudentContact(Long id); + + /** + * 批量删除学生联系人 + * + * @param ids 编号 + */ + void deleteStudentContactListByIds(List ids); + + /** + * 获得学生联系人 + * + * @param id 编号 + * @return 学生联系人 + */ + InfraStudentContactDO getStudentContact(Long id); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任分页 + * + * @param pageReqVO 分页查询 + * @param studentId 学生编号 + * @return 学生班主任分页 + */ + PageResult getStudentTeacherPage(PageParam pageReqVO, Long studentId); + + /** + * 创建学生班主任 + * + * @param studentTeacher 创建信息 + * @return 编号 + */ + Long createStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher); + + /** + * 更新学生班主任 + * + * @param studentTeacher 更新信息 + */ + void updateStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher); + + /** + * 删除学生班主任 + * + * @param id 编号 + */ + void deleteStudentTeacher(Long id); + + /** + * 批量删除学生班主任 + * + * @param ids 编号 + */ + void deleteStudentTeacherListByIds(List ids); + + /** + * 获得学生班主任 + * + * @param id 编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacher(Long id); + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImpl b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImpl new file mode 100644 index 0000000..6c86267 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImpl @@ -0,0 +1,216 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + // 返回 + return student.getId(); + } + + @Override + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudentListByIds(List ids) { + // 删除 + studentMapper.deleteByIds(ids); + + // 删除子表 + deleteStudentContactByStudentIds(ids); + deleteStudentTeacherByStudentIds(ids); + } + + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public PageResult getStudentContactPage(PageParam pageReqVO, Long studentId) { + return studentContactMapper.selectPage(pageReqVO, studentId); + } + + @Override + public Long createStudentContact(InfraStudentContactDO studentContact) { + studentContact.clean(); // 清理掉创建、更新时间等相关属性值 + studentContactMapper.insert(studentContact); + return studentContact.getId(); + } + + @Override + public void updateStudentContact(InfraStudentContactDO studentContact) { + // 校验存在 + validateStudentContactExists(studentContact.getId()); + // 更新 + studentContact.clean(); // 解决更新情况下:updateTime 不更新 + studentContactMapper.updateById(studentContact); + } + + @Override + public void deleteStudentContact(Long id) { + // 删除 + studentContactMapper.deleteById(id); + } + + @Override + public void deleteStudentContactListByIds(List ids) { + // 删除 + studentContactMapper.deleteByIds(ids); + } + + @Override + public InfraStudentContactDO getStudentContact(Long id) { + return studentContactMapper.selectById(id); + } + + private void validateStudentContactExists(Long id) { + if (studentContactMapper.selectById(id) == null) { + throw exception(STUDENT_CONTACT_NOT_EXISTS); + } + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + private void deleteStudentContactByStudentIds(List studentIds) { + studentContactMapper.deleteByStudentIds(studentIds); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public PageResult getStudentTeacherPage(PageParam pageReqVO, Long studentId) { + return studentTeacherMapper.selectPage(pageReqVO, studentId); + } + + @Override + public Long createStudentTeacher(InfraStudentTeacherDO studentTeacher) { + // 校验是否已经存在 + if (studentTeacherMapper.selectByStudentId(studentTeacher.getStudentId()) != null) { + throw exception(STUDENT_TEACHER_EXISTS); + } + // 插入 + studentTeacher.clean(); // 清理掉创建、更新时间等相关属性值 + studentTeacherMapper.insert(studentTeacher); + return studentTeacher.getId(); + } + + @Override + public void updateStudentTeacher(InfraStudentTeacherDO studentTeacher) { + // 校验存在 + validateStudentTeacherExists(studentTeacher.getId()); + // 更新 + studentTeacher.clean(); // 解决更新情况下:updateTime 不更新 + studentTeacherMapper.updateById(studentTeacher); + } + + @Override + public void deleteStudentTeacher(Long id) { + // 删除 + studentTeacherMapper.deleteById(id); + } + + @Override + public void deleteStudentTeacherListByIds(List ids) { + // 删除 + studentTeacherMapper.deleteByIds(ids); + } + + @Override + public InfraStudentTeacherDO getStudentTeacher(Long id) { + return studentTeacherMapper.selectById(id); + } + + private void validateStudentTeacherExists(Long id) { + if (studentTeacherMapper.selectById(id) == null) { + throw exception(STUDENT_TEACHER_NOT_EXISTS); + } + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + + private void deleteStudentTeacherByStudentIds(List studentIds) { + studentTeacherMapper.deleteByStudentIds(studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImplTest b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImplTest new file mode 100644 index 0000000..f1d3bb9 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentServiceImplTest @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherDO new file mode 100644 index 0000000..c19cf9f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherMapper new file mode 100644 index 0000000..0e84a58 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentTeacherMapper @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default PageResult selectPage(PageParam reqVO, Long studentId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(InfraStudentTeacherDO::getStudentId, studentId) + .orderByDesc(InfraStudentTeacherDO::getId)); + } + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentIds(List studentIds) { + return deleteBatch(InfraStudentTeacherDO::getStudentId, studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/h2 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/h2 new file mode 100644 index 0000000..6c1875f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/sql b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/sql new file mode 100644 index 0000000..c0e5f74 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/sql/sql @@ -0,0 +1,54 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/ts/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/ts/index new file mode 100644 index 0000000..0fd0ce5 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/ts/index @@ -0,0 +1,125 @@ +import type { PageParam, PageResult } from '@/http/types' +import { http } from '@/http/http' + +/** 学生联系人信息 */ +export interface StudentContact { + id?: number + studentId: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video?: string + memo: string + createTime?: number +} + +/** 学生班主任信息 */ +export interface StudentTeacher { + id?: number + studentId: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video?: string + memo: string + createTime?: number +} + +/** 学生信息 */ +export interface Student { + id?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video: string + memo: string + createTime?: number +} + +/** 获取学生分页列表 */ +export function getStudentPage(params: PageParam) { + return http.get>('/infra/student/page', params) +} + +/** 获取学生详情 */ +export function getStudent(id: number) { + return http.get(`/infra/student/get?id=${id}`) +} + +/** 创建学生 */ +export function createStudent(data: Student) { + return http.post('/infra/student/create', data) +} + +/** 更新学生 */ +export function updateStudent(data: Student) { + return http.put('/infra/student/update', data) +} + +/** 删除学生 */ +export function deleteStudent(id: number) { + return http.delete(`/infra/student/delete?id=${id}`) +} + +// ==================== 子表:学生联系人 ==================== + +/** 获取学生联系人分页列表 */ +export function getStudentContactPage(params: PageParam & { studentId: number }) { + return http.get>('/infra/student/student-contact/page', params) +} + +/** 获取学生联系人详情 */ +export function getStudentContact(id: number) { + return http.get(`/infra/student/student-contact/get?id=${id}`) +} + +/** 创建学生联系人 */ +export function createStudentContact(data: StudentContact) { + return http.post('/infra/student/student-contact/create', data) +} + +/** 更新学生联系人 */ +export function updateStudentContact(data: StudentContact) { + return http.put('/infra/student/student-contact/update', data) +} + +/** 删除学生联系人 */ +export function deleteStudentContact(id: number) { + return http.delete(`/infra/student/student-contact/delete?id=${id}`) +} + +// ==================== 子表:学生班主任 ==================== + +/** 获取学生班主任分页列表 */ +export function getStudentTeacherPage(params: PageParam & { studentId: number }) { + return http.get>('/infra/student/student-teacher/page', params) +} + +/** 获取学生班主任详情 */ +export function getStudentTeacher(id: number) { + return http.get(`/infra/student/student-teacher/get?id=${id}`) +} + +/** 创建学生班主任 */ +export function createStudentTeacher(data: StudentTeacher) { + return http.post('/infra/student/student-teacher/create', data) +} + +/** 更新学生班主任 */ +export function updateStudentTeacher(data: StudentTeacher) { + return http.put('/infra/student/student-teacher/update', data) +} + +/** 删除学生班主任 */ +export function deleteStudentTeacher(id: number) { + return http.delete(`/infra/student/student-teacher/delete?id=${id}`) +} diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/detail/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/detail/index new file mode 100644 index 0000000..dfd1881 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/detail/index @@ -0,0 +1,342 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/form/index new file mode 100644 index 0000000..0ab96ec --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/form/index @@ -0,0 +1,191 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/index new file mode 100644 index 0000000..acb1b87 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/index @@ -0,0 +1,169 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/search-form b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/search-form new file mode 100644 index 0000000..0928d14 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/search-form @@ -0,0 +1,116 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-contact/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-contact/form/index new file mode 100644 index 0000000..0cd009d --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-contact/form/index @@ -0,0 +1,153 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-teacher/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-teacher/form/index new file mode 100644 index 0000000..cf44ec4 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/vue/student-teacher/form/index @@ -0,0 +1,153 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/xml/InfraStudentMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/xml/InfraStudentMapper new file mode 100644 index 0000000..155aa5c --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/assert.json b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/assert.json new file mode 100644 index 0000000..0a37471 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/assert.json @@ -0,0 +1,67 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-uniapp/src/api/infra/demo/index.ts" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/index.vue" +}, { + "contentPath" : "vue/search-form", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/components/search-form.vue" +}, { + "contentPath" : "vue/form/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/form/index.vue" +}, { + "contentPath" : "vue/detail/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/detail/index.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/ErrorCodeConstants_手动操作 new file mode 100644 index 0000000..a4df7d2 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactDO new file mode 100644 index 0000000..17c668e --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactMapper new file mode 100644 index 0000000..9f16dcf --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentContactMapper @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default List selectListByStudentId(Long studentId) { + return selectList(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentIds(List studentIds) { + return deleteBatch(InfraStudentContactDO::getStudentId, studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentController b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentController new file mode 100644 index 0000000..0c9a9f9 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentController @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除学生") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentList(@RequestParam("ids") List ids) { + studentService.deleteStudentListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/list-by-student-id") + @Operation(summary = "获得学生联系人列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactListByStudentId(studentId)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/get-by-student-id") + @Operation(summary = "获得学生班主任") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentDO new file mode 100644 index 0000000..f39fef2 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentDO @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentMapper new file mode 100644 index 0000000..34e70a0 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentPageReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentPageReqVO new file mode 100644 index 0000000..52d7a23 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentPageReqVO @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO new file mode 100644 index 0000000..12166f4 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.idev.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentSaveReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentSaveReqVO new file mode 100644 index 0000000..4cde1f8 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentSaveReqVO @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + + @Schema(description = "学生联系人列表") + private List studentContacts; + + @Schema(description = "学生班主任") + private InfraStudentTeacherDO studentTeacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentService b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentService new file mode 100644 index 0000000..0a3ee84 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentService @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 批量删除学生 + * + * @param ids 编号 + */ + void deleteStudentListByIds(List ids); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人列表 + * + * @param studentId 学生编号 + * @return 学生联系人列表 + */ + List getStudentContactListByStudentId(Long studentId); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任 + * + * @param studentId 学生编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId); + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImpl b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImpl new file mode 100644 index 0000000..31d689e --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImpl @@ -0,0 +1,191 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + + // 插入子表 + createStudentContactList(student.getId(), createReqVO.getStudentContacts()); + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher()); + // 返回 + return student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + + // 更新子表 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts()); + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudentListByIds(List ids) { + // 删除 + studentMapper.deleteByIds(ids); + + // 删除子表 + deleteStudentContactByStudentIds(ids); + deleteStudentTeacherByStudentIds(ids); + } + + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public List getStudentContactListByStudentId(Long studentId) { + return studentContactMapper.selectListByStudentId(studentId); + } + + private void createStudentContactList(Long studentId, List list) { + if (CollUtil.isEmpty(list)) { + return; + } + list.forEach(o -> o.setStudentId(studentId).clean()); + studentContactMapper.insertBatch(list); + } + + private void updateStudentContactList(Long studentId, List list) { + list.forEach(o -> o.setStudentId(studentId).clean()); + List oldList = studentContactMapper.selectListByStudentId(studentId); + List> diffList = diffList(oldList, list, (oldVal, newVal) -> { + boolean same = ObjectUtil.equal(oldVal.getId(), newVal.getId()); + if (same) { + newVal.setId(oldVal.getId()).clean(); // 解决更新情况下:updateTime 不更新 + } + return same; + }); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + studentContactMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + studentContactMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + studentContactMapper.deleteByIds(convertList(diffList.get(2), InfraStudentContactDO::getId)); + } + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + private void deleteStudentContactByStudentIds(List studentIds) { + studentContactMapper.deleteByStudentIds(studentIds); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) { + return studentTeacherMapper.selectByStudentId(studentId); + } + + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacherMapper.insert(studentTeacher); + } + + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId).clean();// 解决更新情况下:updateTime 不更新 + studentTeacherMapper.insertOrUpdate(studentTeacher); + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + + private void deleteStudentTeacherByStudentIds(List studentIds) { + studentTeacherMapper.deleteByStudentIds(studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImplTest b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImplTest new file mode 100644 index 0000000..f1d3bb9 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentServiceImplTest @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherDO new file mode 100644 index 0000000..c19cf9f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherMapper new file mode 100644 index 0000000..ae4f27d --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentTeacherMapper @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentIds(List studentIds) { + return deleteBatch(InfraStudentTeacherDO::getStudentId, studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/h2 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/h2 new file mode 100644 index 0000000..6c1875f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/sql b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/sql new file mode 100644 index 0000000..c0e5f74 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/sql/sql @@ -0,0 +1,54 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/ts/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/ts/index new file mode 100644 index 0000000..c98bd3b --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/ts/index @@ -0,0 +1,87 @@ +import type { PageParam, PageResult } from '@/http/types' +import { http } from '@/http/http' + +/** 学生联系人信息 */ +export interface StudentContact { + id?: number + studentId?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video?: string + memo: string + createTime?: number +} + +/** 学生班主任信息 */ +export interface StudentTeacher { + id?: number + studentId?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video?: string + memo: string + createTime?: number +} + +/** 学生信息 */ +export interface Student { + id?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video: string + memo: string + createTime?: number + studentContacts?: StudentContact[] + studentTeacher?: StudentTeacher | null +} + +/** 获取学生分页列表 */ +export function getStudentPage(params: PageParam) { + return http.get>('/infra/student/page', params) +} + +/** 获取学生详情 */ +export function getStudent(id: number) { + return http.get(`/infra/student/get?id=${id}`) +} + +/** 创建学生 */ +export function createStudent(data: Student) { + return http.post('/infra/student/create', data) +} + +/** 更新学生 */ +export function updateStudent(data: Student) { + return http.put('/infra/student/update', data) +} + +/** 删除学生 */ +export function deleteStudent(id: number) { + return http.delete(`/infra/student/delete?id=${id}`) +} + +// ==================== 子表:学生联系人 ==================== + +/** 获取学生联系人列表 */ +export function getStudentContactListByStudentId(studentId: number) { + return http.get(`/infra/student/student-contact/list-by-student-id?studentId=${studentId}`) +} + +// ==================== 子表:学生班主任 ==================== + +/** 获取学生班主任 */ +export function getStudentTeacherByStudentId(studentId: number) { + return http.get(`/infra/student/student-teacher/get-by-student-id?studentId=${studentId}`) +} diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/detail/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/detail/index new file mode 100644 index 0000000..829c797 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/detail/index @@ -0,0 +1,229 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/form/index new file mode 100644 index 0000000..b533ad5 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/form/index @@ -0,0 +1,458 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/index new file mode 100644 index 0000000..acb1b87 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/index @@ -0,0 +1,169 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/search-form b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/search-form new file mode 100644 index 0000000..0928d14 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/vue/search-form @@ -0,0 +1,116 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/xml/InfraStudentMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/xml/InfraStudentMapper new file mode 100644 index 0000000..155aa5c --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/assert.json b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/assert.json new file mode 100644 index 0000000..0a37471 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/assert.json @@ -0,0 +1,67 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-uniapp/src/api/infra/demo/index.ts" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/index.vue" +}, { + "contentPath" : "vue/search-form", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/components/search-form.vue" +}, { + "contentPath" : "vue/form/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/form/index.vue" +}, { + "contentPath" : "vue/detail/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/detail/index.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/ErrorCodeConstants_手动操作 new file mode 100644 index 0000000..a4df7d2 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactDO new file mode 100644 index 0000000..17c668e --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactMapper new file mode 100644 index 0000000..9f16dcf --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentContactMapper @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default List selectListByStudentId(Long studentId) { + return selectList(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentIds(List studentIds) { + return deleteBatch(InfraStudentContactDO::getStudentId, studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentController b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentController new file mode 100644 index 0000000..0c9a9f9 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentController @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除学生") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentList(@RequestParam("ids") List ids) { + studentService.deleteStudentListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/list-by-student-id") + @Operation(summary = "获得学生联系人列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactListByStudentId(studentId)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/get-by-student-id") + @Operation(summary = "获得学生班主任") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentDO new file mode 100644 index 0000000..f39fef2 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentDO @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentMapper new file mode 100644 index 0000000..34e70a0 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentPageReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentPageReqVO new file mode 100644 index 0000000..52d7a23 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentPageReqVO @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO new file mode 100644 index 0000000..12166f4 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.idev.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentSaveReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentSaveReqVO new file mode 100644 index 0000000..4cde1f8 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentSaveReqVO @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + + @Schema(description = "学生联系人列表") + private List studentContacts; + + @Schema(description = "学生班主任") + private InfraStudentTeacherDO studentTeacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentService b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentService new file mode 100644 index 0000000..0a3ee84 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentService @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 批量删除学生 + * + * @param ids 编号 + */ + void deleteStudentListByIds(List ids); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人列表 + * + * @param studentId 学生编号 + * @return 学生联系人列表 + */ + List getStudentContactListByStudentId(Long studentId); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任 + * + * @param studentId 学生编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId); + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImpl b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImpl new file mode 100644 index 0000000..31d689e --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImpl @@ -0,0 +1,191 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + + // 插入子表 + createStudentContactList(student.getId(), createReqVO.getStudentContacts()); + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher()); + // 返回 + return student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + + // 更新子表 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts()); + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudentListByIds(List ids) { + // 删除 + studentMapper.deleteByIds(ids); + + // 删除子表 + deleteStudentContactByStudentIds(ids); + deleteStudentTeacherByStudentIds(ids); + } + + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public List getStudentContactListByStudentId(Long studentId) { + return studentContactMapper.selectListByStudentId(studentId); + } + + private void createStudentContactList(Long studentId, List list) { + if (CollUtil.isEmpty(list)) { + return; + } + list.forEach(o -> o.setStudentId(studentId).clean()); + studentContactMapper.insertBatch(list); + } + + private void updateStudentContactList(Long studentId, List list) { + list.forEach(o -> o.setStudentId(studentId).clean()); + List oldList = studentContactMapper.selectListByStudentId(studentId); + List> diffList = diffList(oldList, list, (oldVal, newVal) -> { + boolean same = ObjectUtil.equal(oldVal.getId(), newVal.getId()); + if (same) { + newVal.setId(oldVal.getId()).clean(); // 解决更新情况下:updateTime 不更新 + } + return same; + }); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + studentContactMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + studentContactMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + studentContactMapper.deleteByIds(convertList(diffList.get(2), InfraStudentContactDO::getId)); + } + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + private void deleteStudentContactByStudentIds(List studentIds) { + studentContactMapper.deleteByStudentIds(studentIds); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) { + return studentTeacherMapper.selectByStudentId(studentId); + } + + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacherMapper.insert(studentTeacher); + } + + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId).clean();// 解决更新情况下:updateTime 不更新 + studentTeacherMapper.insertOrUpdate(studentTeacher); + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + + private void deleteStudentTeacherByStudentIds(List studentIds) { + studentTeacherMapper.deleteByStudentIds(studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImplTest b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImplTest new file mode 100644 index 0000000..f1d3bb9 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentServiceImplTest @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherDO new file mode 100644 index 0000000..c19cf9f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherMapper new file mode 100644 index 0000000..ae4f27d --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentTeacherMapper @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentIds(List studentIds) { + return deleteBatch(InfraStudentTeacherDO::getStudentId, studentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/h2 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/h2 new file mode 100644 index 0000000..6c1875f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/sql b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/sql new file mode 100644 index 0000000..c0e5f74 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/sql/sql @@ -0,0 +1,54 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/ts/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/ts/index new file mode 100644 index 0000000..c98bd3b --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/ts/index @@ -0,0 +1,87 @@ +import type { PageParam, PageResult } from '@/http/types' +import { http } from '@/http/http' + +/** 学生联系人信息 */ +export interface StudentContact { + id?: number + studentId?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video?: string + memo: string + createTime?: number +} + +/** 学生班主任信息 */ +export interface StudentTeacher { + id?: number + studentId?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video?: string + memo: string + createTime?: number +} + +/** 学生信息 */ +export interface Student { + id?: number + name: string + description: string + birthday: number + sex: number + enabled: boolean + avatar: string + video: string + memo: string + createTime?: number + studentContacts?: StudentContact[] + studentTeacher?: StudentTeacher | null +} + +/** 获取学生分页列表 */ +export function getStudentPage(params: PageParam) { + return http.get>('/infra/student/page', params) +} + +/** 获取学生详情 */ +export function getStudent(id: number) { + return http.get(`/infra/student/get?id=${id}`) +} + +/** 创建学生 */ +export function createStudent(data: Student) { + return http.post('/infra/student/create', data) +} + +/** 更新学生 */ +export function updateStudent(data: Student) { + return http.put('/infra/student/update', data) +} + +/** 删除学生 */ +export function deleteStudent(id: number) { + return http.delete(`/infra/student/delete?id=${id}`) +} + +// ==================== 子表:学生联系人 ==================== + +/** 获取学生联系人列表 */ +export function getStudentContactListByStudentId(studentId: number) { + return http.get(`/infra/student/student-contact/list-by-student-id?studentId=${studentId}`) +} + +// ==================== 子表:学生班主任 ==================== + +/** 获取学生班主任 */ +export function getStudentTeacherByStudentId(studentId: number) { + return http.get(`/infra/student/student-teacher/get-by-student-id?studentId=${studentId}`) +} diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/detail/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/detail/index new file mode 100644 index 0000000..829c797 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/detail/index @@ -0,0 +1,229 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/form/index new file mode 100644 index 0000000..b533ad5 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/form/index @@ -0,0 +1,458 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/index new file mode 100644 index 0000000..acb1b87 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/index @@ -0,0 +1,169 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/search-form b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/search-form new file mode 100644 index 0000000..0928d14 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/vue/search-form @@ -0,0 +1,116 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/xml/InfraStudentMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/xml/InfraStudentMapper new file mode 100644 index 0000000..155aa5c --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/ts/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/ts/index index da8643a..85b1ac7 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/ts/index +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/ts/index @@ -6,13 +6,13 @@ export interface Student { id?: number name: string description: string - birthday: Date + birthday: number sex: number enabled: boolean avatar: string video: string memo: string - createTime?: Date + createTime?: number } /** 获取学生分页列表 */ @@ -38,4 +38,4 @@ export function updateStudent(data: Student) { /** 删除学生 */ export function deleteStudent(id: number) { return http.delete(`/infra/student/delete?id=${id}`) -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/detail/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/detail/index index d6972ec..8d44124 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/detail/index +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/detail/index @@ -38,7 +38,7 @@ 删除 @@ -51,6 +51,7 @@ import type { Student } from '@/api/infra/demo' import { onUnload } from '@dcloudio/uni-app' import { onMounted, ref } from 'vue' +import { useDialog } from '@wot-ui/ui/components/wd-dialog' import { useToast } from '@wot-ui/ui/components/wd-toast' import { deleteStudent, getStudent } from '@/api/infra/demo' import { useAccess } from '@/hooks/useAccess' @@ -59,7 +60,7 @@ import { DICT_TYPE } from '@/utils/constants' import { formatDateTime } from '@/utils/date' const props = defineProps<{ - id?: number | any + id?: number }>() definePage({ @@ -70,6 +71,7 @@ definePage({ }) const { hasAccessByCodes } = useAccess() +const dialog = useDialog() const toast = useToast() const formData = ref() // 详情数据 const deleting = ref(false) // 删除状态 @@ -100,28 +102,27 @@ function handleEdit() { } /** 删除学生 */ -function handleDelete() { +async function handleDelete() { if (!props.id) { return } - uni.showModal({ - title: '提示', - content: '确定要删除该学生吗?', - success: async (res) => { - if (!res.confirm) { - return - } - deleting.value = true - try { - await deleteStudent(props.id) - toast.success('删除成功') - uni.$emit('infra:demo:reload') - delay(handleBack) - } finally { - deleting.value = false - } - }, - }) + try { + await dialog.confirm({ + title: '提示', + msg: '确定要删除该学生吗?', + }) + } catch { + return + } + deleting.value = true + try { + await deleteStudent(props.id) + toast.success('删除成功') + uni.$emit('infra:demo:reload') + delay(handleBack) + } finally { + deleting.value = false + } } /** 初始化 */ diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/form/index index 06e1a54..0ab96ec 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/form/index +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/vue/form/index @@ -11,14 +11,14 @@ - + - + - - - + - + - + - + import type { FormInstance } from '@wot-ui/ui/components/wd-form/types' -import type { Student } from '@/api/infra/demo' +import type { + Student, +} from '@/api/infra/demo' import { computed, onMounted, ref } from 'vue' import { useToast } from '@wot-ui/ui/components/wd-toast' import { createStudent, getStudent, updateStudent } from '@/api/infra/demo' @@ -104,7 +107,7 @@ import { formatDateTime } from '@/utils/date' import { createFormSchema } from '@/utils/wot' const props = defineProps<{ - id?: number | any + id?: number }>() definePage({ @@ -121,7 +124,7 @@ const formData = ref({ id: undefined, name: '', description: '', - birthday: undefined, + birthday: 0, sex: 0, enabled: false, avatar: '', @@ -163,11 +166,12 @@ async function handleSubmit() { formLoading.value = true try { + const data = formData.value if (props.id) { - await updateStudent(formData.value) + await updateStudent(data) toast.success('修改成功') } else { - await createStudent(formData.value) + await createStudent(data) toast.success('新增成功') } uni.$emit('infra:demo:reload') @@ -178,7 +182,7 @@ async function handleSubmit() { } /** 初始化 */ -onMounted(() => { +onMounted(async () => { getDetail() }) diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/assert.json b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/assert.json new file mode 100644 index 0000000..4086c6e --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/assert.json @@ -0,0 +1,58 @@ +[ { + "contentPath" : "java/InfraCategoryListReqVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategoryListReqVO.java" +}, { + "contentPath" : "java/InfraCategoryRespVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategoryRespVO.java" +}, { + "contentPath" : "java/InfraCategorySaveReqVO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategorySaveReqVO.java" +}, { + "contentPath" : "java/InfraCategoryController", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraCategoryController.java" +}, { + "contentPath" : "java/InfraCategoryDO", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraCategoryDO.java" +}, { + "contentPath" : "java/InfraCategoryMapper", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraCategoryMapper.java" +}, { + "contentPath" : "xml/InfraCategoryMapper", + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraCategoryMapper.xml" +}, { + "contentPath" : "java/InfraCategoryServiceImpl", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryServiceImpl.java" +}, { + "contentPath" : "java/InfraCategoryService", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryService.java" +}, { + "contentPath" : "java/InfraCategoryServiceImplTest", + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-uniapp/src/api/infra/demo/index.ts" +}, { + "contentPath" : "vue/search-form", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/components/search-form.vue" +}, { + "contentPath" : "vue/form/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/form/index.vue" +}, { + "contentPath" : "vue/detail/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/detail/index.vue" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/index.vue" +}, { + "contentPath" : "vue/breadcrumb", + "filePath" : "yudao-ui-admin-uniapp/src/pages-infra/demo/components/breadcrumb.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/ErrorCodeConstants_手动操作 new file mode 100644 index 0000000..42e399f --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,8 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 分类 TODO 补充编号 ========== +ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(TODO 补充编号, "分类不存在"); +ErrorCode CATEGORY_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子分类,无法删除"); +ErrorCode CATEGORY_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级分类不存在"); +ErrorCode CATEGORY_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父分类"); +ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该名字的分类"); +ErrorCode CATEGORY_PARENT_IS_CHILD = new ErrorCode(TODO 补充编号, "不能设置自己的子InfraCategory为父InfraCategory"); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryController b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryController new file mode 100644 index 0000000..7725253 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryController @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraCategoryService; + +@Tag(name = "管理后台 - 分类") +@RestController +@RequestMapping("/infra/category") +@Validated +public class InfraCategoryController { + + @Resource + private InfraCategoryService categoryService; + + @PostMapping("/create") + @Operation(summary = "创建分类") + @PreAuthorize("@ss.hasPermission('infra:category:create')") + public CommonResult createCategory(@Valid @RequestBody InfraCategorySaveReqVO createReqVO) { + return success(categoryService.createCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新分类") + @PreAuthorize("@ss.hasPermission('infra:category:update')") + public CommonResult updateCategory(@Valid @RequestBody InfraCategorySaveReqVO updateReqVO) { + categoryService.updateCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:category:delete')") + public CommonResult deleteCategory(@RequestParam("id") Long id) { + categoryService.deleteCategory(id); + return success(true); + } + + + @GetMapping("/get") + @Operation(summary = "获得分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:category:query')") + public CommonResult getCategory(@RequestParam("id") Long id) { + InfraCategoryDO category = categoryService.getCategory(id); + return success(BeanUtils.toBean(category, InfraCategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得分类列表") + @PreAuthorize("@ss.hasPermission('infra:category:query')") + public CommonResult> getCategoryList(@Valid InfraCategoryListReqVO listReqVO) { + List list = categoryService.getCategoryList(listReqVO); + return success(BeanUtils.toBean(list, InfraCategoryRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出分类 Excel") + @PreAuthorize("@ss.hasPermission('infra:category:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportCategoryExcel(@Valid InfraCategoryListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = categoryService.getCategoryList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "分类.xls", "数据", InfraCategoryRespVO.class, + BeanUtils.toBean(list, InfraCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryDO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryDO new file mode 100644 index 0000000..7705f07 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryDO @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 分类 DO + * + * @author 芋道源码 + */ +@TableName("infra_category") +@KeySequence("infra_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraCategoryDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 父编号 + */ + private Long parentId; + + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryListReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryListReqVO new file mode 100644 index 0000000..e5c6f18 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryListReqVO @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - 分类列表 Request VO") +@Data +public class InfraCategoryListReqVO { + + @Schema(description = "名字", example = "芋头") + private String name; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryMapper new file mode 100644 index 0000000..9dadbf1 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryMapper @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraCategoryMapper extends BaseMapperX { + + default List selectList(InfraCategoryListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(InfraCategoryDO::getName, reqVO.getName()) + .orderByDesc(InfraCategoryDO::getId)); + } + + default InfraCategoryDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(InfraCategoryDO::getParentId, parentId, InfraCategoryDO::getName, name); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(InfraCategoryDO::getParentId, parentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO new file mode 100644 index 0000000..4e77b00 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import cn.idev.excel.annotation.*; + +@Schema(description = "管理后台 - 分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraCategoryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "父编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @ExcelProperty("父编号") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategorySaveReqVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategorySaveReqVO new file mode 100644 index 0000000..5846795 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategorySaveReqVO @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 分类新增/修改 Request VO") +@Data +public class InfraCategorySaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "父编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @NotNull(message = "父编号不能为空") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryService b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryService new file mode 100644 index 0000000..df887b0 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryService @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 分类 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraCategoryService { + + /** + * 创建分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCategory(@Valid InfraCategorySaveReqVO createReqVO); + + /** + * 更新分类 + * + * @param updateReqVO 更新信息 + */ + void updateCategory(@Valid InfraCategorySaveReqVO updateReqVO); + + /** + * 删除分类 + * + * @param id 编号 + */ + void deleteCategory(Long id); + + + /** + * 获得分类 + * + * @param id 编号 + * @return 分类 + */ + InfraCategoryDO getCategory(Long id); + + /** + * 获得分类列表 + * + * @param listReqVO 查询条件 + * @return 分类列表 + */ + List getCategoryList(InfraCategoryListReqVO listReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImpl b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImpl new file mode 100644 index 0000000..ecf3566 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImpl @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraCategoryMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraCategoryServiceImpl implements InfraCategoryService { + + @Resource + private InfraCategoryMapper categoryMapper; + + @Override + public Long createCategory(InfraCategorySaveReqVO createReqVO) { + // 校验父编号的有效性 + validateParentCategory(null, createReqVO.getParentId()); + // 校验名字的唯一性 + validateCategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + InfraCategoryDO category = BeanUtils.toBean(createReqVO, InfraCategoryDO.class); + categoryMapper.insert(category); + + // 返回 + return category.getId(); + } + + @Override + public void updateCategory(InfraCategorySaveReqVO updateReqVO) { + // 校验存在 + validateCategoryExists(updateReqVO.getId()); + // 校验父编号的有效性 + validateParentCategory(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验名字的唯一性 + validateCategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + InfraCategoryDO updateObj = BeanUtils.toBean(updateReqVO, InfraCategoryDO.class); + categoryMapper.updateById(updateObj); + } + + @Override + public void deleteCategory(Long id) { + // 校验存在 + validateCategoryExists(id); + // 校验是否有子分类 + if (categoryMapper.selectCountByParentId(id) > 0) { + throw exception(CATEGORY_EXITS_CHILDREN); + } + // 删除 + categoryMapper.deleteById(id); + } + + + private void validateCategoryExists(Long id) { + if (categoryMapper.selectById(id) == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + } + + private void validateParentCategory(Long id, Long parentId) { + if (parentId == null || CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父分类 + if (Objects.equals(id, parentId)) { + throw exception(CATEGORY_PARENT_ERROR); + } + // 2. 父分类不存在 + CategoryDO parentCategory = categoryMapper.selectById(parentId); + if (parentCategory == null) { + throw exception(CATEGORY_PARENT_NOT_EXITS); + } + // 3. 递归校验父分类,如果父分类是自己的子分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentCategory.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(CATEGORY_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父分类 + if (parentId == null || CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentCategory = categoryMapper.selectById(parentId); + if (parentCategory == null) { + break; + } + } + } + + private void validateCategoryNameUnique(Long id, Long parentId, String name) { + CategoryDO category = categoryMapper.selectByParentIdAndName(parentId, name); + if (category == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的分类 + if (id == null) { + throw exception(CATEGORY_NAME_DUPLICATE); + } + if (!Objects.equals(category.getId(), id)) { + throw exception(CATEGORY_NAME_DUPLICATE); + } + } + + @Override + public InfraCategoryDO getCategory(Long id) { + return categoryMapper.selectById(id); + } + + @Override + public List getCategoryList(InfraCategoryListReqVO listReqVO) { + return categoryMapper.selectList(listReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImplTest b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImplTest new file mode 100644 index 0000000..92672ee --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryServiceImplTest @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraCategoryMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraCategoryServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraCategoryServiceImpl.class) +public class InfraCategoryServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraCategoryServiceImpl categoryService; + + @Resource + private InfraCategoryMapper categoryMapper; + + @Test + public void testCreateCategory_success() { + // 准备参数 + InfraCategorySaveReqVO createReqVO = randomPojo(InfraCategorySaveReqVO.class).setId(null); + + // 调用 + Long categoryId = categoryService.createCategory(createReqVO); + // 断言 + assertNotNull(categoryId); + // 校验记录的属性是否正确 + InfraCategoryDO category = categoryMapper.selectById(categoryId); + assertPojoEquals(createReqVO, category, "id"); + } + + @Test + public void testUpdateCategory_success() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraCategorySaveReqVO updateReqVO = randomPojo(InfraCategorySaveReqVO.class, o -> { + o.setId(dbCategory.getId()); // 设置更新的 ID + }); + + // 调用 + categoryService.updateCategory(updateReqVO); + // 校验是否更新正确 + InfraCategoryDO category = categoryMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, category); + } + + @Test + public void testUpdateCategory_notExists() { + // 准备参数 + InfraCategorySaveReqVO updateReqVO = randomPojo(InfraCategorySaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.updateCategory(updateReqVO), CATEGORY_NOT_EXISTS); + } + + @Test + public void testDeleteCategory_success() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCategory.getId(); + + // 调用 + categoryService.deleteCategory(id); + // 校验数据不存在了 + assertNull(categoryMapper.selectById(id)); + } + + @Test + public void testDeleteCategory_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCategoryList() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class, o -> { // 等会查询到 + o.setName(null); + }); + categoryMapper.insert(dbCategory); + // 测试 name 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); + // 准备参数 + InfraCategoryListReqVO reqVO = new InfraCategoryListReqVO(); + reqVO.setName(null); + + // 调用 + List list = categoryService.getCategoryList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCategory, list.get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/h2 b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/h2 new file mode 100644 index 0000000..4141766 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/h2 @@ -0,0 +1,10 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_category" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" bigint NOT NULL, + PRIMARY KEY ("id") +) COMMENT '分类表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_category"; \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/sql b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/sql new file mode 100644 index 0000000..ccd892d --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/sql/sql @@ -0,0 +1,54 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '分类管理', '', 2, 0, 888, + 'category', '', 'infra/demo/index', 0, 'InfraCategory' +); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类查询', 'infra:category:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类创建', 'infra:category:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类更新', 'infra:category:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类删除', 'infra:category:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类导出', 'infra:category:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/ts/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/ts/index new file mode 100644 index 0000000..3fc4a1c --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/ts/index @@ -0,0 +1,34 @@ +import { http } from '@/http/http' + +/** 分类信息 */ +export interface Category { + id?: number + name: string + parentId: number + children?: Category[] +} + +/** 获取分类列表 */ +export function getCategoryList(params?: Record) { + return http.get('/infra/category/list', params) +} + +/** 获取分类详情 */ +export function getCategory(id: number) { + return http.get(`/infra/category/get?id=${id}`) +} + +/** 创建分类 */ +export function createCategory(data: Category) { + return http.post('/infra/category/create', data) +} + +/** 更新分类 */ +export function updateCategory(data: Category) { + return http.put('/infra/category/update', data) +} + +/** 删除分类 */ +export function deleteCategory(id: number) { + return http.delete(`/infra/category/delete?id=${id}`) +} diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/breadcrumb b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/breadcrumb new file mode 100644 index 0000000..2a76e93 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/breadcrumb @@ -0,0 +1,87 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/detail/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/detail/index new file mode 100644 index 0000000..93d65fa --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/detail/index @@ -0,0 +1,128 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/form/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/form/index new file mode 100644 index 0000000..b39ccfe --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/form/index @@ -0,0 +1,137 @@ + + + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/index b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/index new file mode 100644 index 0000000..064b26b --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/index @@ -0,0 +1,145 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/search-form b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/search-form new file mode 100644 index 0000000..b5616f0 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/vue/search-form @@ -0,0 +1,69 @@ + + + diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/xml/InfraCategoryMapper b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/xml/InfraCategoryMapper new file mode 100644 index 0000000..025ac85 --- /dev/null +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/xml/InfraCategoryMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file -- libgit2 0.21.4