From 7e5256dcd7c88166813492507e9bf7001d893092 Mon Sep 17 00:00:00 2001 From: zhangdaiscott <zhangdaiscott@163.com> Date: Tue, 21 Jun 2022 18:11:10 +0800 Subject: [PATCH] 代码生成器升级 1.支持插入菜单sql生成 2.vue3模板大升级 3.提供vue3原生表单模板生成 --- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeComponents.ftl | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeForm.ftl | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeImport.ftl | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeSearch.ftl | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3Jvxepopup.ftl | 13 +++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3popup.ftl | 17 +++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl | 5 +++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/utils.ftl | 42 +++++++++++++++++++++++++++++++++++++++++- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3MainNative.ftl | 6 ++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub-vue3.ftl | 23 +++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei | 20 ++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 75 +++++++++++++++++++++++++++++++++++++-------------------------------------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei | 11 ++++++++++- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei | 348 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai | 13 +++++-------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi | 3 +-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 83 +++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei | 33 +++++++++++++++++++++++++++++---- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei | 497 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi | 399 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai | 4 +++- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei | 2 +- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei | 34 +++++++++++++++++++++++++++------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 102 ++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/[1-n]List.vuei | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei | 11 ++++++++++- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Modal.vuei | 13 ++++++++++++- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai | 15 ++++++--------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei | 24 ++++++++++++++++++++++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei | 18 +++++++++++++++--- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei | 29 +++++++++++++++++++++++------ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai | 15 ++++++--------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei | 24 ++++++++++++++++++++++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei | 18 +++++++++++++++--- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei | 21 ++++++++++++++++++--- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi | 714 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/[1-n]Form.vuei | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai | 19 ++++++++----------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai | 5 +++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei | 4 ++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei | 24 ++++++++++++++++++++++-- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------ jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql | 1 + jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei | 21 ++++++++++++++++++--- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 6 +++--- jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi | 6 +++++- 98 files changed, 5297 insertions(+), 526 deletions(-) create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeComponents.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeForm.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeImport.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeSearch.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3Jvxepopup.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3popup.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3MainNative.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub-vue3.ftl create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/[1-n]Form.vuei create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql create mode 100644 jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeComponents.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeComponents.ftl new file mode 100644 index 0000000..60ad682 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeComponents.ftl @@ -0,0 +1,48 @@ +<#if need_select_tag> + JDictSelectTag, +</#if> +<#if need_switch> + JSwitch, +</#if> +<#if need_multi> + JSelectMultiple, +</#if> +<#if need_search> + JSearchSelect, +</#if> +<#if need_popup> + JPopup, +</#if> +<#if need_category> + JCategorySelect, +</#if> +<#if need_dept> + JSelectDept, +</#if> +<#if need_dept_user> + JSelectUserByDept, +</#if> +<#if need_select_tree> + JTreeSelect, +</#if> +<#if need_time> + TimePicker, +</#if> +<#if need_pca> + JAreaLinkage, +</#if> +<#if need_upload> + JUpload, +</#if> +<#if need_image_upload> + JImageUpload, +</#if> +<#if need_markdown> + JMarkdownEditor, +</#if> +<#if need_editor> + JEditor, +</#if> +<#if need_checkbox> + JCheckbox, +</#if> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeForm.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeForm.ftl new file mode 100644 index 0000000..8d28821 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeForm.ftl @@ -0,0 +1,107 @@ +<#include "/common/utils.ftl"> +<#if po.isShow =='Y' && po.fieldName != 'id' && isNotPidField(tableVo, po.fieldDbName)> +<#assign form_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictField}"> + </#if> + <a-col :span="${form_span}"> + <a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}"> + <#if po.classType =='date'> + <a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" value-format="YYYY-MM-DD" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType =='datetime'> + <a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" showTime value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType =='time'> + <#assign need_time = true> + <time-picker placeholder="请选择${po.filedComment}" value-format="HH:mm:ss" v-model:value="formData.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType =='popup'> + <#assign need_popup = true> + <#assign sourceFields = po.dictField?default("")?trim?split(",")/> + <#assign targetFields = po.dictText?default("")?trim?split(",")/> + <j-popup + placeholder="请选择${po.filedComment}" + v-model:value="formData.${po.fieldName}" + code="${po.dictTable}" + :fieldConfig="[ + <#list sourceFields as fieldName> + { source: '${fieldName}', target: '${targetFields[fieldName_index]}' }, + </#list> + ]" + :multi="${po.extendParams.popupMulti?c}" + :setFieldsValue="setFieldsValue" + <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if><#rt> + /> + <#elseif po.classType =='sel_depart'> + <#assign need_dept = true> + <j-select-dept v-model:value="formData.${po.fieldName}" :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> /> + <#elseif po.classType =='switch'> + <#assign need_switch = true> + <j-switch v-model:value="formData.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-switch> + <#elseif po.classType =='pca'> + <#assign need_pca = true> + <j-area-linkage v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> /> + <#elseif po.classType =='markdown'> + <#assign need_markdown = true> + <j-markdown-editor v-model:value="formData.${autoStringSuffixForModel(po)}" id="${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-markdown-editor> + <#elseif po.classType =='password'> + <a-input-password v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType =='sel_user'> + <#assign need_dept_user = true> + <j-select-user-by-dept v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType =='textarea'> + <a-textarea v-model:value="formData.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType=='radio'> + <#assign need_select_tag = true> + <j-dict-select-tag type='radio' v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType=='list'> + <#assign need_select_tag = true> + <j-dict-select-tag v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType=='list_multi'> + <#assign need_multi = true> + <j-select-multiple type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> :triggerChange="false"/> + <#elseif po.classType=='checkbox'> + <#assign need_checkbox = true> + <j-checkbox type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType=='sel_search'> + <#assign need_search = true> + <j-search-select v-model:value="formData.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> /> + <#elseif po.classType=='cat_tree'> + <#assign need_category = true> + <j-category-select v-model:value="formData.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}"</#if> <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> @change="(value) => handleFormChange('${po.fieldName}', value)" /> + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + <a-input-number v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.classType=='file'> + <#assign need_upload = true> + <j-upload v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> <#if po.uploadnum??>:maxCount=${po.uploadnum}</#if>></j-upload> + <#elseif po.classType=='image'> + <#assign need_image_upload = true> + <j-image-upload <#if po.uploadnum??>:fileMax=${po.uploadnum}</#if> v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-image-upload> + <#elseif po.classType=='umeditor'> + <#assign need_editor = true> + <j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/> + <#elseif po.fieldDbType=='Blob'> + <a-input v-model:value="formData.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></a-input> + <#elseif po.classType == 'sel_tree'> + <#assign need_select_tree = true> + <j-tree-select + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}" + <#elseif po.dictText?split(',')[1]??> + pidField="${po.dictText?split(',')[1]}" + <#elseif po.dictText?split(',')[3]??> + hasChildField="${po.dictText?split(',')[3]}" + </#if> + </#if> + pidValue="${po.dictField}" + <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> + v-model:value="formData.${po.fieldName}" + @change="(value) => handleFormChange('${po.fieldName}', value)"> + </j-tree-select> + <#else> + <a-input v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></a-input> + </#if> + </a-form-item> + </a-col> +</#if> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeImport.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeImport.ftl new file mode 100644 index 0000000..1c9a3f7 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeImport.ftl @@ -0,0 +1,48 @@ +<#if need_select_tag> + import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue'; +</#if> +<#if need_switch> + import JSwitch from '/@/components/Form/src/jeecg/components/JSwitch.vue'; +</#if> +<#if need_multi> + import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue'; +</#if> +<#if need_search> + import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue'; +</#if> +<#if need_popup> + import JPopup from '/@/components/Form/src/jeecg/components/JPopup.vue'; +</#if> +<#if need_category> + import JCategorySelect from '/@/components/Form/src/jeecg/components/JCategorySelect.vue'; +</#if> +<#if need_dept> + import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue'; +</#if> +<#if need_dept_user> + import JSelectUserByDept from '/@/components/Form/src/jeecg/components/JSelectUserByDept.vue'; +</#if> +<#if need_select_tree> + import JTreeSelect from '/@/components/Form/src/jeecg/components/JTreeSelect.vue'; +</#if> +<#if need_time> + import { TimePicker } from 'ant-design-vue'; +</#if> +<#if need_pca> + import JAreaLinkage from '/@/components/Form/src/jeecg/components/JAreaLinkage.vue'; +</#if> +<#if need_upload> + import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue'; +</#if> +<#if need_image_upload> + import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue'; +</#if> +<#if need_markdown> + import JMarkdownEditor from '/@/components/Form/src/jeecg/components/JMarkdownEditor.vue'; +</#if> +<#if need_editor> + import JEditor from '/@/components/Form/src/jeecg/components/JEditor.vue'; +</#if> +<#if need_checkbox> + import JCheckbox from "/@/components/Form/src/jeecg/components/JCheckbox.vue"; +</#if> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeSearch.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeSearch.ftl new file mode 100644 index 0000000..a16bf89 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/native/vue3NativeSearch.ftl @@ -0,0 +1,85 @@ +<#if po.isQuery=='Y'> +<#assign query_flag=true> + <#if query_field_no==2> + <template v-if="toggleSearchStatus"> + </#if> + <#assign query_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign need_select_tag = true> + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign need_select_tag = true> + <#assign query_field_dictCode="${po.dictField}"> + </#if> + <#if po.queryMode=='single'> + <#if query_field_no gt 1> </#if><a-col :lg="8"> + <#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}"> + <#if po.classType=='sel_search'> + <#if query_field_no gt 1> </#if><j-search-select placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}" /> + <#elseif po.classType=='sel_user'> + <#if query_field_no gt 1> </#if><j-select-user-by-dept placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" /> + <#elseif po.classType=='switch'> + <#if query_field_no gt 1> </#if><j-switch placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> query /> + <#elseif po.classType=='sel_depart'> + <#if query_field_no gt 1> </#if><j-select-dept placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" checkStrictly /> + <#elseif po.classType=='list_multi'> + <#if query_field_no gt 1> </#if><j-select-multiple placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model:value="queryParam.${po.fieldName}" /> + <#elseif po.classType=='cat_tree'> + <#if query_field_no gt 1> </#if><j-category-select placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}" @change="(value) => handleFormChange('${po.fieldName}', value)" /> + <#elseif po.classType=='date'> + <#if query_field_no gt 1> </#if><a-date-picker valueFormat="YYYY-MM-DD" placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" /> + <#elseif po.classType=='datetime'> + <#if query_field_no gt 1> </#if><a-date-picker showTime valueFormat="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" /> + <#elseif po.classType=='pca'> + <#if query_field_no gt 1> </#if><j-area-linkage v-model:value="queryParam.${po.fieldName}" placeholder="请选择${po.filedComment}" @change="(value) => handleAreaChange('${po.fieldName}', value)" /> + <#elseif po.classType=='sel_tree'> + <#if query_field_no gt 1> </#if><j-tree-select v-model:value="queryParam.${po.fieldName}" placeholder="请选择${po.filedComment}" <#if po.dictText??><#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}" <#elseif po.dictText?split(',')[1]??>pidField:"${po.dictText?split(',')[1]}", <#elseif po.dictText?split(',')[3]??>hasChildField:"${po.dictText?split(',')[3]}"</#if> </#if>pidValue="${po.dictField}" /> + <#elseif po.classType=='popup'> + <#assign sourceFields = po.dictField?default("")?trim?split(",")/> + <#assign targetFields = po.dictText?default("")?trim?split(",")/> + <#if query_field_no gt 1> </#if><j-popup + <#if query_field_no gt 1> </#if>placeholder="请选择${po.filedComment}" + <#if query_field_no gt 1> </#if>v-model:value="queryParam.${po.fieldName}" + <#if query_field_no gt 1> </#if>code="${po.dictTable}" + <#if query_field_no gt 1> </#if>:fieldConfig="[ + <#list sourceFields as fieldName> + <#if query_field_no gt 1> </#if>{ source: '${fieldName}', target: '${targetFields[fieldName_index]}' }, + </#list> + <#if query_field_no gt 1> </#if>]" + <#if query_field_no gt 1> </#if>:multi="${po.extendParams.popupMulti?c}" + <#if query_field_no gt 1> </#if>:setFieldsValue="setFieldsValue" /> + <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> + <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> + <#if po.dictTable?default("")?trim?length gt 1> + <#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/> + <#elseif po.dictField?default("")?trim?length gt 1> + <#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictField}"/> + <#else> + <#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}"></a-input> + </#if> + <#else> + <#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}"></a-input> + </#if> + <#if query_field_no gt 1> </#if></a-form-item> + <#if query_field_no gt 1> </#if></a-col> + <#else> + <#if query_field_no gt 1> </#if><a-col :lg="8"> + <#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}"> + <#if po.classType=='date'> + <#if query_field_no gt 1> </#if><a-date-picker value-format="YYYY-MM-DD" placeholder="请选择开始时间" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust"/> + <#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span> + <#if query_field_no gt 1> </#if><a-date-picker value-format="YYYY-MM-DD" placeholder="请选择结束日期" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust"/> + <#elseif po.classType=='datetime'> + <#if query_field_no gt 1> </#if><a-date-picker showTime value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust" /> + <#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span> + <#if query_field_no gt 1> </#if><a-date-picker showTime value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust" /> + <#else> + <#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust"></a-input> + <#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span> + <#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust"></a-input> + </#if> + <#if query_field_no gt 1> </#if></a-form-item> + <#if query_field_no gt 1> </#if></a-col> + </#if> + <#assign query_field_no=query_field_no+1> + </#if> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3Jvxepopup.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3Jvxepopup.ftl new file mode 100644 index 0000000..3f671e1 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3Jvxepopup.ftl @@ -0,0 +1,13 @@ +<#assign sourceFields = col.dictField?default("")?trim?split(",")/> +<#assign targetFields = col.dictText?default("")?trim?split(",")/> + type: JVxeTypes.popup, + popupCode:"${col.dictTable}", + fieldConfig: [ + <#list sourceFields as fieldName> + { source: '${fieldName}', target: '${targetFields[fieldName_index]}' }, + </#list> + ], + <#if col.readonly=='Y'> + disabled:true, + </#if> + diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3popup.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3popup.ftl new file mode 100644 index 0000000..21deec1 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/form/vue3popup.ftl @@ -0,0 +1,17 @@ +<#assign sourceFields = po.dictField?default("")?trim?split(",")/> +<#assign targetFields = po.dictText?default("")?trim?split(",")/> + component: 'JPopup', + componentProps: ({ formActionType }) => { + const {setFieldsValue} = formActionType; + return{ + setFieldsValue:setFieldsValue, + code:"${po.dictTable}", + fieldConfig: [ + <#list sourceFields as fieldName> + { source: '${fieldName}', target: '${targetFields[fieldName_index]}' }, + </#list> + ], + multi:${po.extendParams.popupMulti?c} + } + }, + diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl new file mode 100644 index 0000000..ac35200 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/sql/menu_insert.ftl @@ -0,0 +1,5 @@ +-- 注意:该页面对应的前台目录为views/${entityPackage}文件夹下 +-- 如果你想更改到其他目录,请修改sql中component字段对应的值 + +INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) +VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}', NULL, '${tableVo.ftlDescription}', '/${entityPackage}/${entityName?uncap_first}List', '${entityPackage}/${entityName}List', NULL, NULL, 0, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0); \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/utils.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/utils.ftl index 0acf2d5..c7c5df6 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/utils.ftl +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/utils.ftl @@ -25,7 +25,7 @@ <#return text?uncap_first> </#function> <#-- 驼峰转下划线 --> -<#function camelToDashed(str, case='normal')> +<#function camelToDashed(str, case='lower')> <#return camelToChar(str, "_", case)> </#function> <#----> @@ -130,4 +130,44 @@ <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}'}"> </#if> </#if> +</#function> + + +<#-- vue3 获取表单modal的宽度--> +<#function getModalWidth fieldRowNum> + <#assign modal_width = 800> + <#if fieldRowNum==2> + <#assign modal_width = 896> + <#elseif fieldRowNum==3> + <#assign modal_width = 1024> + <#elseif fieldRowNum==4> + <#assign modal_width = 1280> + </#if> + <#return modal_width> +</#function> + +<#-- vue3 获取表单 colspan --> +<#function getFormSpan fieldRowNum> + <#assign form_span = 24> + <#if fieldRowNum==2> + <#assign form_span = 12> + <#elseif fieldRowNum==3> + <#assign form_span = 8> + <#elseif fieldRowNum==4> + <#assign form_span = 6> + </#if> + <#return form_span> +</#function> + +<#-- vue3 native 判断字段名不是 pidField --> +<#function isNotPidField(tableVo, fieldDbName) > + <#assign flag = true> + <#if tableVo??> + <#if tableVo.extendParams??> + <#if tableVo.extendParams.pidField?default("")?trim == fieldDbName> + <#assign flag = false> + </#if> + </#if> + </#if> + <#return flag> </#function> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl new file mode 100644 index 0000000..45b269f --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3CoreNative.ftl @@ -0,0 +1,49 @@ +<#assign fieldValidType = po.fieldValidType!''> +<#-- 非空校验 --> +<#if po.nullable == 'N' || fieldValidType == '*'> +{ required: true, message: '请输入${po.filedComment}!'}<#rt>, +<#elseif fieldValidType!=''> +{ required: false}<#rt>, +</#if> +<#-- 唯一校验 --> +<#if fieldValidType == 'only'> + { validator: ${po.fieldName}Duplicatevalidate }<#rt> +<#-- 6到16位数字 --> +<#elseif fieldValidType == 'n6-16'> + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}<#rt>, +<#-- 6到16位任意字符 --> +<#elseif fieldValidType == '*6-16'> + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}<#rt>, +<#-- 6到18位字符串 --> +<#elseif fieldValidType == 's6-18'> + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}<#rt>, +<#-- 网址 --> +<#elseif fieldValidType == 'url'> + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}<#rt>, +<#-- 电子邮件 --> +<#elseif fieldValidType == 'e'> + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}<#rt>, +<#-- 手机号码 --> +<#elseif fieldValidType == 'm'> + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}<#rt>, +<#-- 邮政编码 --> +<#elseif fieldValidType == 'p'> + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}<#rt>, +<#-- 字母 --> +<#elseif fieldValidType == 's'> + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}<#rt>, +<#-- 数字 --> +<#elseif fieldValidType == 'n'> + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}<#rt>, +<#-- 整数 --> +<#elseif fieldValidType == 'z'> + { pattern: /^-?\d+$/, message: '请输入整数!'}<#rt>, +<#-- 金额 --> +<#elseif fieldValidType == 'money'> + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}<#rt>, +<#-- 正则校验 --> +<#elseif fieldValidType != '' && fieldValidType != '*'> + { pattern: '${fieldValidType}', message: '不符合校验规则!'}<#rt>, +<#else> + <#t> +</#if> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3MainNative.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3MainNative.ftl new file mode 100644 index 0000000..e941c4d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/native/vue3MainNative.ftl @@ -0,0 +1,6 @@ +<#include "../../utils.ftl"> +<#list columns as po> + <#if po.isShow == 'Y' && poHasCheck(po)> + ${po.fieldName}: [<#include "vue3CoreNative.ftl">], + </#if> +</#list> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub-vue3.ftl b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub-vue3.ftl new file mode 100644 index 0000000..d405358 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub-vue3.ftl @@ -0,0 +1,23 @@ +<#include "../utils.ftl"> + <#if col.isShow == 'Y' && poHasCheck(col)> + validateRules: [ + <#if col.fieldName != 'id'> + <#assign subFieldValidType = col.fieldValidType!''> + <#-- 非空校验 --> + <#if col.nullable == 'N' || fieldValidType == '*'> + { required: true, message: '${'$'}{title}不能为空' }, + <#elseif fieldValidType!=''> + { required: false}, + </#if> + <#-- 其他情况下,只要有值就被认为是正则校验 --> + <#if subFieldValidType?length gt 0> + <#assign subMessage = '格式不正确'> + <#if subFieldValidType == 'only' > + <#assign subMessage = '不能重复'> + </#if> + { pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" } + <#t> + </#if> + </#if> + ], + </#if> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index 024fa25..8ffddae 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -36,9 +37,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei index c0b44d9..3a46fab 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -48,7 +48,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if> /> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -58,7 +58,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index 167fb6a..3a85e4b 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -46,6 +46,10 @@ <template #htmlSlot="{text}"> <div v-html="text"></div> </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> <template #fileSlot="{text}"> <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> @@ -64,6 +68,10 @@ import ${entityName}Modal from './components/${entityName}Modal.vue' import {columns, searchFormSchema} from './${entityName}.data'; import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; + import { downloadFile } from '/@/utils/common/renderUtils'; + <#if list_need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; + </#if> <#if list_need_category> import { loadCategoryData } from '/@/api/common/api' import { getAuthCache, setAuthCache } from '/@/utils/auth'; @@ -84,6 +92,17 @@ schemas: searchFormSchema, autoSubmitOnEnter:true, showAdvancedButton:true, + fieldMapToNumber: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']], + </#if> + </#if> + </#if> + </#list> + ], fieldMapToTime: [ <#list columns as po> <#if po.isQuery=='Y'> @@ -100,6 +119,7 @@ }, actionColumn: { width: 120, + fixed:'right' }, }, exportConfig: { diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index dc4cd58..7087240 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> import {BasicColumn} from '/@/components/Table'; import {FormSchema} from '/@/components/Table'; import { rules} from '/@/utils/helper/validator'; @@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -56,7 +57,7 @@ export const columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -83,7 +84,7 @@ export const searchFormSchema: FormSchema[] = [ <#if po.queryMode=='single'> { label: "${po.filedComment}", - field: "${po.fieldName}", + field: ${autoStringSuffix(po)}, <#if po.classType=='sel_search'> component: 'JSearchSelect', componentProps:{ @@ -94,17 +95,23 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='switch'> component: 'JSwitch', componentProps:{ + query:true, <#if po.dictField != 'is_open'> - options:"${po.dictField}" + options:${po.dictField} </#if> }, <#elseif po.classType=='sel_depart'> component: 'JSelectDept', <#elseif po.classType=='list_multi'> - component: 'JMultiSelectTag',//暂无该组件 + component: 'JSelectMultiple', componentProps:{ - dictCode:"query_field_dictCode?default("")" - }, + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true + }, <#elseif po.classType=='cat_tree'> component: 'JCategorySelect', componentProps:{ @@ -117,19 +124,15 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, + <#elseif po.classType =='time'> + component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType=='pca'> component: 'JAreaLinkage', <#elseif po.classType=='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:"${po.dictField}", - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> component: 'JDictSelectTag', @@ -156,6 +159,8 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', <#else> component: 'Input', //TODO 范围查询 </#if> @@ -188,27 +193,22 @@ export const formSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime: true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -230,14 +230,14 @@ export const formSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -272,7 +272,7 @@ export const formSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -290,7 +290,6 @@ export const formSchema: FormSchema[] = [ <#else> component: 'Input', </#if> - <#include "/common/utils.ftl"> <#if po.isShow == 'Y' && poHasCheck(po)> dynamicRules: ({model,schema}) => { <#if po.fieldName != 'id'> @@ -304,16 +303,16 @@ export const formSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei index fd54ae4..51dcb22 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei @@ -1,5 +1,6 @@ +<#include "/common/utils.ftl"> <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> <BasicForm @register="registerForm"/> </BasicModal> </template> @@ -18,6 +19,7 @@ labelWidth: 150, schemas: formSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); //表单赋值 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { @@ -54,5 +56,12 @@ </script> <style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + :deep(.ant-calendar-picker){ + width: 100% + } </style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei new file mode 100644 index 0000000..7961187 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei @@ -0,0 +1,348 @@ +<template> + <div> +<#assign query_field_no=0> +<#assign need_category = false> +<#assign need_pca = false> +<#assign need_search = false> +<#assign need_dept_user = false> +<#assign need_switch = false> +<#assign need_dept = false> +<#assign need_multi = false> +<#assign need_popup = false> +<#assign need_select_tag = false> +<#assign need_select_tree = false> +<#assign need_time = false> +<#assign bpm_flag=false> +<#assign need_markdown = false> +<#assign need_upload = false> +<#assign need_image_upload = false> +<#assign need_editor = false> +<#assign need_checkbox = false> +<#assign query_flag = false> + <!--查询区域--> + <div class="jeecg-basic-table-form-container"> + <a-form @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol"> + <a-row :gutter="24"> +<#-- 开始循环 --> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0> +<#assign need_category=true> +</#if> +<#if po.classType=='pca'> +<#assign need_pca=true> +</#if> +<#if po.classType=='sel_search'> +<#assign need_search = true> +</#if> +<#if po.classType=='sel_user'> +<#assign need_dept_user = true> +</#if> +<#if po.classType=='sel_depart'> +<#assign need_dept = true> +</#if> +<#if po.classType=='switch'> +<#assign need_switch = true> +</#if> +<#if po.classType=='list_multi'> +<#assign need_multi = true> +</#if> +<#if po.classType=='popup'> +<#assign need_popup = true> +</#if> +<#if po.classType=='sel_tree'> +<#assign need_select_tree = true> +</#if> +<#if po.classType=='time'> +<#assign need_time = true> +</#if> + <#include "/common/form/native/vue3NativeSearch.ftl"> +</#list> +<#if query_field_no gt 2> + </template> +</#if> +<#if query_flag> + <a-col :xl="6" :lg="7" :md="8" :sm="24"> + <span style="float: left; overflow: hidden" class="table-page-search-submitButtons"> + <a-col :lg="6"> + <a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button> + <a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button> + <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px"> + {{ toggleSearchStatus ? '收起' : '展开' }} + <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" /> + </a> + </a-col> + </span> + </a-col> +</#if> + </a-row> + </a-form> + </div> +<#-- 结束循环 --> + <!--引用表格--> + <BasicTable @register="registerTable" :rowSelection="rowSelection"> + <!--插槽:table标题--> + <template #tableTitle> + <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button> + <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button> + <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> + <a-dropdown v-if="selectedRowKeys.length > 0"> + <template #overlay> + <a-menu> + <a-menu-item key="1" @click="batchHandleDelete"> + <Icon icon="ant-design:delete-outlined"></Icon> + 删除 + </a-menu-item> + </a-menu> + </template> + <a-button>批量操作 + <Icon icon="mdi:chevron-down"></Icon> + </a-button> + </a-dropdown> + </template> + <!--操作栏--> + <template #action="{ record }"> + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/> + </template> + <!--字段回显插槽--> + <template #htmlSlot="{text}"> + <div v-html="text"></div> + </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> + <template #fileSlot="{text}"> + <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> + </template> + </BasicTable> + <!-- 表单区域 --> + <${entityName}Modal ref="registerModal" @success="handleSuccess"></${entityName}Modal> + </div> +</template> + +<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup> + import { ref, reactive } from 'vue'; + import { BasicTable, useTable, TableAction } from '/@/components/Table'; + import { useListPage } from '/@/hooks/system/useListPage'; + import { columns } from './${entityName}.data'; + import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './${entityName}.api'; + import { downloadFile } from '/@/utils/common/renderUtils'; + import ${entityName}Modal from './components/${entityName}Modal.vue' + <#include "/common/form/native/vue3NativeImport.ftl"> +<#if need_category> + import { loadCategoryData } from '/@/api/common/api'; + import { getAuthCache, setAuthCache } from '/@/utils/auth'; + import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum'; +</#if> +<#if need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; +</#if> + + const queryParam = ref<any>({}); + const toggleSearchStatus = ref<boolean>(false); + const registerModal = ref(); + //注册table数据 + const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ + tableProps: { + title: '${tableVo.ftlDescription}', + api: list, + columns, + canResize:false, + useSearchForm: false, + actionColumn: { + width: 120, + fixed: 'right', + }, + beforeFetch: (params) => { + return Object.assign(params, queryParam.value); + }, + }, + exportConfig: { + name: "${tableVo.ftlDescription}", + url: getExportUrl, + }, + importConfig: { + url: getImportUrl, + success: handleSuccess + }, + }); + const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext; + const labelCol = reactive({ + xs: { span: 24 }, + sm: { span: 7 }, + }); + const wrapperCol = reactive({ + xs: { span: 24 }, + sm: { span: 16 }, + }); + + /** + * 新增事件 + */ + function handleAdd() { + registerModal.value.disableSubmit = false; + registerModal.value.add(); + } + + /** + * 编辑事件 + */ + function handleEdit(record: Recordable) { + registerModal.value.disableSubmit = false; + registerModal.value.edit(record); + } + + /** + * 详情 + */ + function handleDetail(record: Recordable) { + registerModal.value.disableSubmit = true; + registerModal.value.edit(record); + } + + /** + * 删除事件 + */ + async function handleDelete(record) { + await deleteOne({ id: record.id }, handleSuccess); + } + + /** + * 批量删除事件 + */ + async function batchHandleDelete() { + await batchDelete({ ids: selectedRowKeys.value }, handleSuccess); + } + + /** + * 成功回调 + */ + function handleSuccess() { + (selectedRowKeys.value = []) && reload(); + } + + /** + * 操作栏 + */ + function getTableAction(record) { + return [ + { + label: '编辑', + onClick: handleEdit.bind(null, record), + }, + ]; + } + + /** + * 下拉操作栏 + */ + function getDropDownAction(record) { + return [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, + { + label: '删除', + popConfirm: { + title: '是否确认删除', + confirm: handleDelete.bind(null, record), + }, + }, + ]; + } + + /** + * 查询 + */ + function searchQuery() { + reload(); + } + + /** + * 重置 + */ + function searchReset() { + queryParam.value = {}; + selectedRowKeys.value = []; + //刷新数据 + reload(); + } + + <#if need_popup> + /** + * popup组件值改变事件 + */ + function setFieldsValue(map) { + Object.keys(map).map((key) => { + queryParam.value[key] = map[key]; + }); + } + </#if> + + <#if need_pca> + /** + * 省市区点击事件 + * @param key + * @param value + */ + function handleAreaChange(key, value) { + queryParam.value[key] = value.join(','); + } + </#if> + + <#if need_category> + /** + * form点击事件 + * @param value + */ + function handleFormChange(key, value) { + queryParam.value[key] = value; + } + + /** + * 初始化字典配置 + */ + function initDictConfig() { + <#list columns as po> + <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'> + <#if po.classType=='cat_tree' && need_category==true> + loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => { + if (res) { + let allDictDate = getAuthCache(DB_DICT_DATA_KEY); + if(!allDictDate['${po.dictField?default("")}']){ + Object.assign(allDictDate,{'${po.dictField?default("")}':res}) + } + setAuthCache(DB_DICT_DATA_KEY,allDictDate) + } + }); + </#if> + </#if> + </#list> + } + initDictConfig(); + </#if> +</script> + +<style lang="less" scoped> + .jeecg-basic-table-form-container { + .table-page-search-submitButtons { + display: block; + margin-bottom: 24px; + white-space: nowrap; + } + .query-group-cust{ + width: calc(50% - 15px); + min-width: 100px !important; + } + .query-group-split-cust{ + width: 30px; + display: inline-block; + text-align: center + } + } +</style> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi new file mode 100644 index 0000000..75dfbdf --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi @@ -0,0 +1,69 @@ +import { defHttp } from '/@/utils/http/axios'; +import { Modal } from 'ant-design-vue'; + +enum Api { + list = '/${entityPackage}/${entityName?uncap_first}/list', + save='/${entityPackage}/${entityName?uncap_first}/add', + edit='/${entityPackage}/${entityName?uncap_first}/edit', + deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete', + deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch', + importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel', + exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls', +} + +/** + * 导出api + * @param params + */ +export const getExportUrl = Api.exportXls; + +/** + * 导入api + */ +export const getImportUrl = Api.importExcel; + +/** + * 列表接口 + * @param params + */ +export const list = (params) => defHttp.get({ url: Api.list, params }); + +/** + * 删除单个 + * @param params + * @param handleSuccess + */ +export const deleteOne = (params,handleSuccess) => { + return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => { + handleSuccess(); + }); +} + +/** + * 批量删除 + * @param params + * @param handleSuccess + */ +export const batchDelete = (params, handleSuccess) => { + Modal.confirm({ + title: '确认删除', + content: '是否删除选中数据', + okText: '确认', + cancelText: '取消', + onOk: () => { + return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => { + handleSuccess(); + }); + } + }); +} + +/** + * 保存或者更新 + * @param params + * @param isUpdate + */ +export const saveOrUpdate = (params, isUpdate) => { + let url = isUpdate ? Api.edit : Api.save; + return defHttp.post({ url: url, params }, { isTransformResponse: false }); +} diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi new file mode 100644 index 0000000..03a5779 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi @@ -0,0 +1,366 @@ +<#include "/common/utils.ftl"> +import {BasicColumn} from '/@/components/Table'; +import {FormSchema} from '/@/components/Table'; +import { rules} from '/@/utils/helper/validator'; +import { render } from '/@/utils/common/renderUtils'; +//列表数据 +export const columns: BasicColumn[] = [ + <#list columns as po> + <#if po.isShowList =='Y' && po.fieldName !='id'> + { + title: '${po.filedComment}', + align: "center", + <#if po.sort=='Y'> + sorter: true, + </#if> + <#if po.classType=='date'> + dataIndex: '${po.fieldName}', + customRender:({text}) =>{ + return !text?"":(text.length>10?text.substr(0,10):text); + }, + <#elseif po.fieldDbType=='Blob'> + dataIndex: '${po.fieldName}String' + <#elseif po.classType=='umeditor'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'htmlSlot' }, + <#elseif po.classType=='pca'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'pcaSlot' }, + <#elseif po.classType=='file'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'fileSlot' }, + <#elseif po.classType=='image'> + dataIndex: '${po.fieldName}', + customRender: render.renderImage, + <#elseif po.classType=='switch'> + dataIndex: '${po.fieldName}', +<#assign switch_extend_arr=['Y','N']> +<#if po.dictField?default("")?contains("[")> +<#assign switch_extend_arr=po.dictField?eval> +</#if> +<#list switch_extend_arr as a> +<#if a_index == 0> +<#assign switch_extend_arr1=a> +<#else> +<#assign switch_extend_arr2=a> +</#if> +</#list> + customRender:({text}) => { + return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]); + }, + <#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'> + dataIndex: '${po.fieldName}_dictText' + <#elseif po.classType=='cat_tree'> + dataIndex: '${po.fieldName}', + <#if po.dictText?default("")?trim?length == 0> + customRender:({text}) => { + return render.renderCategoryTree(text,'${po.dictField?default("")}'); + }, + <#else> + customRender: ({text, record}) => (text ? record['${po.dictText}'] : ''); + </#if> + <#else> + dataIndex: '${po.fieldName}' + </#if> + }, + </#if> + </#list> +]; + +//查询数据 +export const searchFormSchema: FormSchema[] = [ +<#-- 开始循环 --> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.isQuery=='Y'> +<#assign query_flag=true> + <#assign query_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign query_field_dictCode="${po.dictField}"> + </#if> +<#if po.queryMode=='single'> + { + label: "${po.filedComment}", + field: ${autoStringSuffix(po)}, +<#if po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps:{ + dict: "${po.dictTable},${po.dictText},${po.dictField}" + }, +<#elseif po.classType=='sel_user'> + component: 'JSelectUserByDept', +<#elseif po.classType=='switch'> + component: 'JSwitch', + componentProps:{ + <#if po.dictField != 'is_open'> + options: "${po.dictField}" + </#if> + }, + <#elseif po.classType=='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType=='list_multi'> + component: 'JSelectMultiple', + componentProps: { + <#if po.dictTable?default("")?trim?length gt 1> + dictCode: "${po.dictTable},${po.dictText},${po.dictField}" + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode: "${po.dictField}" + </#if> + }, + <#elseif po.classType=='cat_tree'> + component: 'JCategorySelect', + componentProps:{ + pcode: "${po.dictField?default("")}",//back和事件未添加,暂时有问题 + }, +<#elseif po.classType=='date'> + component: 'DatePicker', +<#elseif po.classType=='datetime'> + component: 'DatePicker', + componentProps: { + showTime: true, + }, + <#elseif po.classType =='time'> + component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss', + }, +<#elseif po.classType=='pca'> + component: 'JAreaLinkage', +<#elseif po.classType=='popup'> + <#include "/common/form/vue3popup.ftl"> +<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> +<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> + component: 'JDictSelectTag', + componentProps:{ + <#if po.dictTable?default("")?trim?length gt 1> + dictCode: "${po.dictTable},${po.dictText},${po.dictField}" + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode: "${po.dictField}" + </#if> + }, +<#else> + component: 'Input', +</#if> + colProps: {span: 6}, + }, +<#else> + { + label: "${po.filedComment}", + field: "${po.fieldName}", +<#if po.classType=='date'> + component: 'RangePicker', +<#elseif po.classType=='datetime'> + component: 'RangePicker', + componentProps: { + showTime: true, + }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', +<#else> + component: 'Input', //TODO 范围查询 +</#if> + colProps: {span: 6}, + }, +</#if> +</#if> +</#list> +<#-- 结束循环 --> +]; + +//表单数据 +export const formSchema: FormSchema[] = [ +<#assign form_cat_tree = false> +<#assign form_cat_back = ""> +<#assign bpm_flag=false> +<#assign id_exists = false> +<#list columns as po><#rt/> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.fieldDbName == 'id'> + <#assign id_exists = true> +</#if> +<#if po.isShow =='Y'> +<#assign form_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictField}"> + </#if> + { + label: '${po.filedComment}', + field: ${autoStringSuffix(po)}, + <#if po.classType =='date'> + component: 'DatePicker', + <#elseif po.classType =='datetime'> + component: 'DatePicker', + componentProps: { + showTime: true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' + }, + <#elseif po.classType =='time'> + component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, + <#elseif po.classType =='popup'> + <#include "/common/form/vue3popup.ftl"> + <#elseif po.classType =='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType =='switch'> + component: 'JSwitch', + componentProps:{ + <#if po.dictField != 'is_open'> + options: ${po.dictField} + </#if> + }, + <#elseif po.classType =='pca'> + component: 'JAreaLinkage', + <#elseif po.classType =='markdown'> + component: 'JMarkdownEditor',//注意string转换问题 + <#elseif po.classType =='password'> + component: 'InputPassword', + <#elseif po.classType =='sel_user'> + component: 'JSelectUserByDept', + componentProps:{ + labelKey: 'realname', + }, + <#elseif po.classType =='textarea'> + component: 'InputTextArea', + <#elseif po.classType=='list' || po.classType=='radio'> + component: 'JDictSelectTag', + componentProps:{ + dictCode: "${form_field_dictCode}" + }, + <#elseif po.classType=='list_multi' || po.classType=='checkbox'> + component: 'JSelectMultiple', + componentProps:{ + dictCode: "${form_field_dictCode}" + }, + <#elseif po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps:{ + dict: "${form_field_dictCode}" + }, +<#elseif po.classType=='cat_tree'> + <#assign form_cat_tree = true> + component: 'JCategorySelect', + componentProps:{ + pcode: "${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题 + }, + <#if po.dictText?default("")?trim?length gt 1> + <#assign form_cat_back = "${po.dictText}"> + </#if> + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'InputNumber', + <#elseif po.classType=='file'> + component: 'JUpload', + componentProps:{ + <#if po.uploadnum??> + maxCount: ${po.uploadnum} + </#if> + }, + <#elseif po.classType=='image'> + component: 'JImageUpload', + componentProps:{ + <#if po.uploadnum??> + fileMax: ${po.uploadnum} + </#if> + }, + <#elseif po.classType=='umeditor'> + component: 'JEditor', + <#elseif po.classType == 'sel_tree'> + component: 'JTreeSelect', + componentProps:{ + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict: "${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}", + <#elseif po.dictText?split(',')[1]??> + pidField: "${po.dictText?split(',')[1]}", + <#elseif po.dictText?split(',')[3]??> + hasChildField: "${po.dictText?split(',')[3]}", + </#if> + </#if> + pidValue: "${po.dictField}", + }, + <#else> + component: 'Input', + </#if> + <#if po.isShow == 'Y' && poHasCheck(po)> + dynamicRules: ({model,schema}) => { + <#if po.fieldName != 'id'> + <#assign fieldValidType = po.fieldValidType!''> + return [ + <#-- 非空校验 --> + <#if po.nullable == 'N' || fieldValidType == '*'> + { required: true, message: '请输入${po.filedComment}!'}, + <#elseif fieldValidType!=''> + { required: false}, + </#if> + <#-- 唯一校验 --> + <#if fieldValidType == 'only'> + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, + <#-- 6到16位数字 --> + <#elseif fieldValidType == 'n6-16'> + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, + <#-- 6到16位任意字符 --> + <#elseif fieldValidType == '*6-16'> + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, + <#-- 6到18位字符串 --> + <#elseif fieldValidType == 's6-18'> + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + <#-- 网址 --> + <#elseif fieldValidType == 'url'> + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, + <#-- 电子邮件 --> + <#elseif fieldValidType == 'e'> + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}, + <#-- 手机号码 --> + <#elseif fieldValidType == 'm'> + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, + <#-- 邮政编码 --> + <#elseif fieldValidType == 'p'> + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + <#-- 字母 --> + <#elseif fieldValidType == 's'> + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, + <#-- 数字 --> + <#elseif fieldValidType == 'n'> + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}, + <#-- 整数 --> + <#elseif fieldValidType == 'z'> + { pattern: /^-?\d+$/, message: '请输入整数!'}, + <#-- 金额 --> + <#elseif fieldValidType == 'money'> + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}, + <#-- 正则校验 --> + <#elseif fieldValidType != '' && fieldValidType != '*'> + { pattern: '${fieldValidType}', message: '不符合校验规则!'}, + <#-- 无校验 --> + <#else> + <#t> + </#if> + ]; + </#if> + }, + </#if> + <#if po.readonly=='Y'> + dynamicDisabled: true + </#if> + }, +</#if> +</#list> +<#if id_exists == false> + // TODO 主键隐藏字段,目前写死为ID + { + label: '', + field: 'id', + component: 'Input', + show: false, + }, +</#if> +]; diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei new file mode 100644 index 0000000..0a835d2 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei @@ -0,0 +1,185 @@ +<#include "/common/utils.ftl"> +<template> + <a-spin :spinning="confirmLoading"> + <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-row> +<#assign need_category = false> +<#assign bpm_flag=false> +<#assign need_pca = false> +<#assign need_search = false> +<#assign need_dept_user = false> +<#assign need_switch = false> +<#assign need_dept = false> +<#assign need_multi = false> +<#assign need_popup = false> +<#assign need_select_tag = false> +<#assign need_select_tree = false> +<#assign need_time = false> +<#assign need_markdown = false> +<#assign need_upload = false> +<#assign need_image_upload = false> +<#assign need_editor = false> +<#assign need_checkbox = false> +<#assign hasOnlyValidate = false> +<#assign form_span = 24> +<#if tableVo.fieldRowNum==2> +<#assign form_span = 12> +<#elseif tableVo.fieldRowNum==3> +<#assign form_span = 8> +<#elseif tableVo.fieldRowNum==4> +<#assign form_span = 6> +</#if> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + <#assign hasOnlyValidate = true> +</#if> + <#include "/common/form/native/vue3NativeForm.ftl"> +</#list> + </a-row> + </a-form> + </a-spin> +</template> + +<script lang="ts" setup> + import { ref, reactive, defineExpose, nextTick, defineProps, computed } from 'vue'; + import { defHttp } from '/@/utils/http/axios'; + import { useMessage } from '/@/hooks/web/useMessage'; + import moment from 'moment'; + <#include "/common/form/native/vue3NativeImport.ftl"> + import { getValueType } from '/@/utils'; + import { saveOrUpdate } from '../${entityName}.api'; + import { Form } from 'ant-design-vue'; + <#if hasOnlyValidate == true> + import { duplicateValidate } from '/@/utils/helper/validator' + </#if> + + const props = defineProps({ + disabled: { type: Boolean, default: false }, + }); + const formRef = ref(); + const useForm = Form.useForm; + const emit = defineEmits(['register', 'ok']); + const formData = reactive<Record<string, any>>({ +<#list columns as po> + <#if po.isShow == 'Y'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ${po.fieldName}: undefined, + <#elseif po.fieldDbType=='Blob'> + ${po.fieldName}String: '', + <#else> + ${po.fieldName}: '', + </#if> + </#if> +</#list> + }); + const { createMessage } = useMessage(); + const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } }); + const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } }); + const confirmLoading = ref<boolean>(false); + //表单验证 + const validatorRules = { + <#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl"> + }; + const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true }); + + /** + * 新增 + */ + function add() { + edit({}); + } + + /** + * 编辑 + */ + function edit(record) { + nextTick(() => { + resetFields(); + //赋值 + Object.assign(formData, record); + }); + } + + /** + * 提交数据 + */ + async function submitForm() { + // 触发表单验证 + await validate(); + confirmLoading.value = true; + const isUpdate = ref<boolean>(false); + //时间格式化 + let model = formData; + if (model.id) { + isUpdate.value = true; + } + //循环数据 + for (let data in model) { + //如果该数据是数组并且是字符串类型 + if (model[data] instanceof Array) { + let valueType = getValueType(formRef.value.getProps, data); + //如果是字符串类型的需要变成以逗号分割的字符串 + if (valueType === 'string') { + model[data] = model[data].join(','); + } + } + } + await saveOrUpdate(model, isUpdate.value) + .then((res) => { + if (res.success) { + createMessage.success(res.message); + emit('ok'); + } else { + createMessage.warning(res.message); + } + }) + .finally(() => { + confirmLoading.value = false; + }); + } + + <#if need_popup> + /** + * popup组件值改变事件 + */ + function setFieldsValue(map) { + Object.keys(map).map((key) => { + formData[key] = map[key]; + }); + } + </#if> + + <#if need_category || need_select_tree> + /** + * 值改变事件触发 + * @param key + * @param value + */ + function handleFormChange(key, value) { + formData[key] = value; + } + </#if> + <#list columns as po> + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + async function ${po.fieldName}Duplicatevalidate(_r, value) { + return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '') + } + </#if> + </#list> + defineExpose({ + add, + edit, + submitForm, + }); +</script> + +<style lang="less" scoped> + .antd-modal-form { + height: 500px !important; + overflow-y: auto; + padding: 24px 24px 24px 24px; + } +</style> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei new file mode 100644 index 0000000..391bb77 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei @@ -0,0 +1,75 @@ +<template> + <a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭"> + <${entityName}Form ref="registerForm" @ok="submitCallback" :disabled="disableSubmit"></${entityName}Form> + </a-modal> +</template> + +<script lang="ts" setup> + import { ref, nextTick, defineExpose } from 'vue'; + import ${entityName}Form from './${entityName}Form.vue' + + const title = ref<string>(''); + const width = ref<number>(800); + const visible = ref<boolean>(false); + const disableSubmit = ref<boolean>(false); + const registerForm = ref(); + const emit = defineEmits(['register', 'success']); + + /** + * 新增 + */ + function add() { + title.value = '新增'; + visible.value = true; + nextTick(() => { + registerForm.value.add(); + }); + } + + /** + * 编辑 + * @param record + */ + function edit(record) { + title.value = disableSubmit.value ? '详情' : '编辑'; + visible.value = true; + nextTick(() => { + registerForm.value.edit(record); + }); + } + + /** + * 确定按钮点击事件 + */ + function handleOk() { + registerForm.value.submitForm(); + } + + /** + * form保存回调事件 + */ + function submitCallback() { + handleCancel(); + emit('success'); + } + + /** + * 取消按钮回调事件 + */ + function handleCancel() { + visible.value = false; + } + + defineExpose({ + add, + edit, + disableSubmit, + }); +</script> + +<style> + /**隐藏样式-modal确定按钮 */ + .jee-hidden { + display: none !important; + } +</style> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai index 43919c8..b1d90eb 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -205,17 +205,14 @@ public class ${entityName}Controller { QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - //Step.2 获取导出数据 - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); - // 过滤选中数据 + //配置选中数据查询条件 String selections = request.getParameter("selections"); - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); - if(oConvertUtils.isEmpty(selections)) { - ${entityName?uncap_first}List = queryList; - }else { + if(oConvertUtils.isNotEmpty(selections)) { List<String> selectionList = Arrays.asList(selections.split(",")); - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + queryWrapper.in("id",selectionList); } + //Step.2 获取导出数据 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper); // Step.3 组装pageList List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index 2c9aba3..8ed5d49 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai index cfc7129..7530402 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as subTab> #segment#${subTab.entityName}.java package ${bussiPackage}.${entityPackage}.entity; @@ -32,9 +33,9 @@ public class ${subTab.entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei index 5cd51c9..255ab0a 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -48,7 +48,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -58,7 +58,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei index 80dc0f7..acb82d2 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -44,7 +44,7 @@ :multi="${po.extendParams.popupMulti?c}" @input="popupCallback"/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch> <#elseif po.classType =='pca'> @@ -54,7 +54,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}"/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index dfcd1b3..f3975bd 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -32,9 +33,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei index 2c8a29d..2f5ff3f 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -56,9 +56,9 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index 98b2908..d71792a 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -8,6 +8,13 @@ <#assign hasChildrenField = po.fieldName> </#if> </#list> +<#assign list_need_pca=false> +<#-- 开始循环 --> +<#list columns as po> +<#if po.classType=='pca'> +<#assign list_need_pca=true> +</#if> +</#list> <template> <div> <!--引用表格--> @@ -34,8 +41,20 @@ </template> <!--操作栏--> <template #action="{ record }"> - <TableAction :actions="getTableAction(record)"/> + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/> </template> + <!--字段回显插槽--> + <template #htmlSlot="{text}"> + <div v-html="text"></div> + </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> + <template #fileSlot="{text}"> + <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> + </template> </BasicTable> <!--字典弹窗--> <${entityName}Modal @register="registerModal" @success="handleSuccess"/> @@ -49,9 +68,12 @@ import {useModal} from '/@/components/Modal'; import { useListPage } from '/@/hooks/system/useListPage' import ${entityName}Modal from './components/${entityName}Modal.vue'; - import {columns} from './${entityName}.data'; + import {columns,searchFormSchema} from './${entityName}.data'; + import { downloadFile } from '/@/utils/common/renderUtils'; import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api'; - + <#if list_need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; + </#if> const expandedRowKeys = ref([]); //字典model const [registerModal, {openModal}] = useModal(); @@ -62,6 +84,36 @@ title: '${tableVo.ftlDescription}', columns, canResize:false, + formConfig: { + labelWidth: 120, + schemas: searchFormSchema, + autoSubmitOnEnter:true, + showAdvancedButton:true, + fieldMapToNumber: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']], + </#if> + </#if> + </#if> + </#list> + ], + fieldMapToTime: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.classType=='date'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'], + <#elseif po.classType=='datetime'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'], + </#if> + </#if> + </#if> + </#list> + ], + }, actionColumn: { width: 240, }, @@ -120,13 +172,13 @@ */ async function batchHandleDelete() { const ids = selectedRowKeys.value.filter(item => !item.includes('loading')) - await batchDelete${entityName}({ids: ids}, importSuccess); + await batchDelete${entityName}({id: ids}, importSuccess); } /** * 导入 */ function importSuccess() { - reload() && (expandedRowKeys.value = []); + (selectedRowKeys.value = []) && reload(); } /** * 添加下级 @@ -140,12 +192,16 @@ /** * 成功回调 */ - async function handleSuccess({isUpdate, values, expandedArr}) { + async function handleSuccess({isUpdate, values, expandedArr, changeParent}) { if (isUpdate) { - //编辑回调 - updateTableDataRecord(values.id, values); + if (changeParent) { + reload(); + } else { + // 编辑回调 + updateTableDataRecord(values.id, values); + } } else { - if(!values['${pidFieldName}']){ + if(!values['id'] || !values['${pidFieldName}']){ //新增根节点 reload(); }else{ @@ -264,18 +320,28 @@ onClick: handleEdit.bind(null, record), }, { - label: '删除', - popConfirm: { - title: '确定删除吗?', - confirm: handleDelete.bind(null, record), - }, - }, - { label: '添加下级', onClick: handleAddSub.bind(null, {${pidFieldName}: record.id}), } ] } + /** + * 下拉操作栏 + */ + function getDropDownAction(record){ + return [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, { + label: '删除', + popConfirm: { + title: '确定删除吗?', + confirm: handleDelete.bind(null, record), + } + } + ] + } </script> <style scoped> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi index 2cbeee0..8b52377 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__api.tsi @@ -6,7 +6,6 @@ enum Api { save='/${entityPackage}/${entityName?uncap_first}/add', edit='/${entityPackage}/${entityName?uncap_first}/edit', delete${entityName} = '/${entityPackage}/${entityName?uncap_first}/delete', - deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch', importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel', exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls', loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot', @@ -49,7 +48,7 @@ export const batchDelete${entityName} = (params, handleSuccess) => { okText: '确认', cancelText: '取消', onOk: () => { - return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => { + return defHttp.delete({url: Api.delete${entityName}, data: params}, {joinParamsToUrl: true}).then(() => { handleSuccess(); }); } diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index d83a727..f9e2486 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> import {BasicColumn} from '/@/components/Table'; import {FormSchema} from '/@/components/Table'; import { rules} from '/@/utils/helper/validator'; @@ -28,7 +29,7 @@ export const columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -60,7 +61,7 @@ export const columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -105,9 +106,14 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='sel_depart'> component: 'JSelectDept', <#elseif po.classType=='list_multi'> - component: 'JMultiSelectTag',//暂无该组件 - componentProps:{ - dictCode:"query_field_dictCode?default("")" + component: 'JSelectMultiple', + componentProps:{ + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true }, <#elseif po.classType=='cat_tree'> component: 'JCategorySelect', @@ -124,15 +130,22 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='pca'> component: 'JAreaLinkage', <#elseif po.classType=='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:"${po.dictField}", - multi:${po.extendParams.popupMulti?c}, - } + <#include "/common/form/vue3popup.ftl"> +<#elseif po.classType == 'sel_tree'> + component: 'JTreeSelect', + componentProps:{ + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}", + </#if> + <#if po.dictText?split(',')[1]??> + pidField:"${po.dictText?split(',')[1]}", + </#if> + <#if po.dictText?split(',')[3]??> + hasChildField:"${po.dictText?split(',')[3]}", + </#if> + </#if> + pidValue:"${po.dictField}", }, <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> @@ -160,6 +173,13 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, +<#elseif po.classType == 'time'> + component: 'TimePicker', + componentProps:{ + valueFormat: 'HH:mm:ss', + }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', <#else> component: 'Input', //TODO 范围查询 </#if> @@ -192,7 +212,7 @@ export const formSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.fieldDbName == tableVo.extendParams.pidField> component: 'JTreeSelect', componentProps: { @@ -203,24 +223,19 @@ export const formSchema: FormSchema[] = [ }, <#elseif po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD hh:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps:{ + valueFormat: 'HH:mm:ss', + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -242,14 +257,14 @@ export const formSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -284,7 +299,7 @@ export const formSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -318,16 +333,16 @@ export const formSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei index a4294d7..c513462 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#assign pidFieldName = ""> <#assign hasChildrenField = ""> <#list originalColumns as po> @@ -9,7 +10,7 @@ </#if> </#list> <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit"> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :title="getTitle" @ok="handleSubmit"> <BasicForm @register="registerForm"/> </BasicModal> </template> @@ -24,10 +25,13 @@ const isUpdate = ref(true); const expandedRowKeys = ref([]); const treeData = ref([]); + // 当前编辑的数据 + let model:Nullable<Recordable> = null; //表单配置 - const [registerForm, {resetFields, setFieldsValue, validate, updateSchema}] = useForm({ + const [registerForm, {setProps,resetFields, setFieldsValue, validate, updateSchema}] = useForm({ schemas: formSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}, labelCol: { xs: { span: 24 }, sm: { span: 4 }, @@ -42,16 +46,21 @@ //重置表单 await resetFields(); expandedRowKeys.value = []; - setModalProps({confirmLoading: false, minHeight: 80}); + setModalProps({confirmLoading: false, minHeight: 80 ,showOkBtn: !!!data?.hideFooter}); isUpdate.value = !!data?.isUpdate; if (data?.record) { + model = data.record; //表单赋值 await setFieldsValue({ ...data.record, }); + } else { + model = null; } //父级节点树信息 treeData.value = await loadTreeData({'async': false,'pcode':''}); + // 隐藏底部时禁用整个表单 + setProps({ disabled: !!data?.hideFooter }) }); //设置标题 const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑')); @@ -85,9 +94,25 @@ //展开的节点信息 await getExpandKeysByPid(values['${pidFieldName}'],unref(treeData)) //刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息) - emit('success', {isUpdate: unref(isUpdate), values:{...values},expandedArr: unref(expandedRowKeys).reverse()}); + emit('success', { + isUpdate: unref(isUpdate), + values: {...values}, + expandedArr: unref(expandedRowKeys).reverse(), + // 是否更改了父级节点 + changeParent: model != null && (model['${pidFieldName}'] != values['${pidFieldName}']), + }); } finally { setModalProps({confirmLoading: false}); } } </script> +<style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + + :deep(.ant-calendar-picker){ + width: 100% + } +</style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei new file mode 100644 index 0000000..39a9f3c --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei @@ -0,0 +1,497 @@ +<template> + <div> +<#assign pidFieldName = ""> +<#assign hasChildrenField = ""> +<#list originalColumns as po> + <#if po.fieldDbName == tableVo.extendParams.pidField> + <#assign pidFieldName = po.fieldName> + </#if> + <#if po.fieldDbName == tableVo.extendParams.hasChildren> + <#assign hasChildrenField = po.fieldName> + </#if> +</#list> +<#assign query_field_no=0> +<#assign need_category = false> +<#assign need_pca = false> +<#assign need_search = false> +<#assign need_dept_user = false> +<#assign need_switch = false> +<#assign need_dept = false> +<#assign need_multi = false> +<#assign need_popup = false> +<#assign need_select_tag = false> +<#assign need_select_tree = false> +<#assign need_time = false> +<#assign bpm_flag=false> +<#assign need_markdown = false> +<#assign need_upload = false> +<#assign need_image_upload = false> +<#assign need_editor = false> +<#assign need_checkbox = false> +<#assign query_flag = false> + <!--查询区域--> + <div class="jeecg-basic-table-form-container"> + <a-form @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol"> + <a-row :gutter="24"> +<#-- 开始循环 --> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0> +<#assign need_category=true> +</#if> +<#if po.classType=='pca'> +<#assign need_pca=true> +</#if> +<#if po.classType=='sel_search'> +<#assign need_search = true> +</#if> +<#if po.classType=='sel_user'> +<#assign need_dept_user = true> +</#if> +<#if po.classType=='sel_depart'> +<#assign need_dept = true> +</#if> +<#if po.classType=='switch'> +<#assign need_switch = true> +</#if> +<#if po.classType=='list_multi'> +<#assign need_multi = true> +</#if> +<#if po.classType=='popup'> +<#assign need_popup = true> +</#if> +<#if po.classType=='sel_tree'> +<#assign need_select_tree = true> +</#if> +<#if po.classType=='time'> +<#assign need_time = true> +</#if> + <#include "/common/form/native/vue3NativeSearch.ftl"> +</#list> +<#if query_field_no gt 2> + </template> +</#if> +<#if query_flag> + <a-col :xl="6" :lg="7" :md="8" :sm="24"> + <span style="float: left; overflow: hidden" class="table-page-search-submitButtons"> + <a-col :lg="6"> + <a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button> + <a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button> + <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px"> + {{ toggleSearchStatus ? '收起' : '展开' }} + <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" /> + </a> + </a-col> + </span> + </a-col> +</#if> + </a-row> + </a-form> + </div> +<#-- 结束循环 --> + <!--引用表格--> + <BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess"> + <!--插槽:table标题--> + <template #tableTitle> + <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button> + <a-dropdown v-if="selectedRowKeys.length > 0"> + <template #overlay> + <a-menu> + <a-menu-item key="1" @click="batchHandleDelete"> + <Icon icon="ant-design:delete-outlined"></Icon> + 删除 + </a-menu-item> + </a-menu> + </template> + <a-button + >批量操作 + <Icon icon="ant-design:down-outlined"></Icon> + </a-button> + </a-dropdown> + </template> + <!--操作栏--> + <template #action="{ record }"> + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" /> + </template> + <!--字段回显插槽--> + <template #htmlSlot="{ text }"> + <div v-html="text"></div> + </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{ text }"> + {{ getAreaTextByCode(text) }} + </template> + <template #fileSlot="{ text }"> + <span v-if="!text" style="font-size: 12px; font-style: italic">无文件</span> + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> + </template> + </BasicTable> + <!-- 表单区域 --> + <${entityName}Modal ref="registerModal" @success="handleSuccess"></${entityName}Modal> + </div> +</template> + +<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup> + import { ref, reactive, unref } from 'vue'; + import { BasicTable, useTable, TableAction } from '/@/components/Table'; + import { useListPage } from '/@/hooks/system/useListPage'; + import { columns } from './${entityName}.data'; + import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api'; + import { downloadFile } from '/@/utils/common/renderUtils'; + import ${entityName}Modal from './components/${entityName}Modal.vue' + <#include "/common/form/native/vue3NativeImport.ftl"> +<#if need_category> + import { loadCategoryData } from '/@/api/common/api'; + import { getAuthCache, setAuthCache } from '/@/utils/auth'; + import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum'; +</#if> +<#if need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; +</#if> + + const expandedRowKeys = ref([]); + const queryParam = ref<any>({}); + const toggleSearchStatus = ref<boolean>(false); + const registerModal = ref(); + //注册table数据 + const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ + tableProps: { + title: '${tableVo.ftlDescription}', + api: list, + columns, + canResize:false, + useSearchForm: false, + actionColumn: { + width: 120, + fixed: 'right', + }, + beforeFetch: (params) => { + return Object.assign(params, queryParam.value); + }, + }, + exportConfig: { + name: "${tableVo.ftlDescription}", + url: getExportUrl, + }, + importConfig: { + url: getImportUrl, + success: success + }, + }); + const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource},{ rowSelection, selectedRowKeys }] = tableContext + const labelCol = reactive({ + xs: { span: 24 }, + sm: { span: 7 }, + }); + const wrapperCol = reactive({ + xs: { span: 24 }, + sm: { span: 16 }, + }); + + /** + * 新增事件 + */ + function handleAdd() { + registerModal.value.disableSubmit = false; + registerModal.value.add(); + } + + /** + * 编辑事件 + */ + async function handleEdit(record) { + registerModal.value.disableSubmit = false; + registerModal.value.edit(record); + } + + /** + * 详情 + */ + async function handleDetail(record) { + registerModal.value.disableSubmit = true; + registerModal.value.edit(record); + } + + /** + * 删除事件 + */ + async function handleDelete(record) { + await delete${entityName}({ id: record.id }, success); + } + + /** + * 批量删除事件 + */ + async function batchHandleDelete() { + const ids = selectedRowKeys.value.filter((item) => !item.includes('loading')); + await batchDelete${entityName}({ id: ids }, success); + } + + /** + * 成功回调刷新页面 + */ + function success() { + (selectedRowKeys.value = []) && reload(); + } + + /** + * 添加下级 + */ + function handleAddSub(record) { + registerModal.value.disableSubmit = false; + registerModal.value.add(record); + } + + /** + * 成功回调 + */ + async function handleSuccess({ isUpdate, values, expandedArr, changeParent }) { + if (isUpdate) { + if (changeParent) { + reload(); + } else { + // 编辑回调 + updateTableDataRecord(values.id, values); + } + } else { + if (!values['id'] || !values['pid']) { + //新增根节点 + reload(); + } else { + //新增子集 + expandedRowKeys.value = []; + for (let key of unref(expandedArr)) { + await expandTreeNode(key); + } + } + } + } + + /** + * 接口请求成功后回调 + */ + function onFetchSuccess(result) { + getDataByResult(result.items) && loadDataByExpandedRows(); + } + + /** + * 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据) + */ + async function loadDataByExpandedRows() { + if (unref(expandedRowKeys).length > 0) { + const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',') }); + if (res.success && res.result.records.length > 0) { + //已展开的数据批量子节点 + let records = res.result.records; + const listMap = new Map(); + for (let item of records) { + let pid = item['${pidFieldName}']; + if (unref(expandedRowKeys).includes(pid)) { + let mapList = listMap.get(pid); + if (mapList == null) { + mapList = []; + } + mapList.push(item); + listMap.set(pid, mapList); + } + } + let childrenMap = listMap; + let fn = (list) => { + if (list) { + list.forEach((data) => { + if (unref(expandedRowKeys).includes(data.id)) { + data.children = getDataByResult(childrenMap.get(data.id)); + fn(data.children); + } + }); + } + }; + fn(getDataSource()); + } + } + } + + /** + * 处理数据集 + */ + function getDataByResult(result) { + if (result && result.length > 0) { + return result.map((item) => { + //判断是否标记了带有子节点 + if (item['hasChild'] == '1') { + let loadChild = { id: item.id + '_loadChild', name: 'loading...', isLoading: true }; + item.children = [loadChild]; + } + return item; + }); + } + } + + /** + *树节点展开合并 + */ + async function handleExpand(expanded, record) { + // 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据 + if (expanded) { + expandedRowKeys.value.push(record.id); + if (record.children.length > 0 && !!record.children[0].isLoading) { + let result = await getChildList({ ${pidFieldName}: record.id}); + result = result.records ? result.records : result; + if (result && result.length > 0) { + record.children = getDataByResult(result); + } else { + record.children = null; + record.hasChild = '0'; + } + } + } else { + let keyIndex = expandedRowKeys.value.indexOf(record.id); + if (keyIndex >= 0) { + expandedRowKeys.value.splice(keyIndex, 1); + } + } + } + + /** + * 操作表格后处理树节点展开合并 + */ + async function expandTreeNode(key) { + let record = findTableDataRecord(key); + expandedRowKeys.value.push(key); + let result = await getChildList({ ${pidFieldName}: key }); + if (result && result.length > 0) { + record.children = getDataByResult(result); + } else { + record.children = null; + record.hasChild = '0'; + } + updateTableDataRecord(key, record); + } + + /** + * 操作栏 + */ + function getTableAction(record) { + return [ + { + label: '编辑', + onClick: handleEdit.bind(null, record), + } + ]; + } + + /** + * 下拉操作栏 + */ + function getDropDownAction(record) { + return [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, + { + label: '添加下级', + onClick: handleAddSub.bind(null, { pid: record.id }), + }, + { + label: '删除', + popConfirm: { + title: '确定删除吗?', + confirm: handleDelete.bind(null, record), + }, + }, + ]; + } + + /** + * 查询 + */ + function searchQuery() { + reload(); + } + + /** + * 重置 + */ + function searchReset() { + queryParam.value = {}; + selectedRowKeys.value = []; + //刷新数据 + reload(); + } + + <#if need_popup> + /** + * popup组件值改变事件 + */ + function setFieldsValue(map) { + Object.keys(map).map((key) => { + queryParam.value[key] = map[key]; + }); + } + </#if> + + <#if need_pca> + /** + * 省市区点击事件 + * @param key + * @param value + */ + function handleAreaChange(key, value) { + queryParam.value[key] = value.join(','); + } + </#if> + + <#if need_category> + /** + * form点击事件 + * @param value + */ + function handleFormChange(key, value) { + queryParam.value[key] = value; + } + + /** + * 初始化字典配置 + */ + function initDictConfig() { + <#list columns as po> + <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'> + <#if po.classType=='cat_tree' && need_category==true> + loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => { + if (res) { + let allDictDate = getAuthCache(DB_DICT_DATA_KEY); + if(!allDictDate['${po.dictField?default("")}']){ + Object.assign(allDictDate,{'${po.dictField?default("")}':res}) + } + setAuthCache(DB_DICT_DATA_KEY,allDictDate) + } + }); + </#if> + </#if> + </#list> + } + initDictConfig(); + </#if> +</script> + +<style lang="less" scoped> + .jeecg-basic-table-form-container { + .table-page-search-submitButtons { + display: block; + margin-bottom: 24px; + white-space: nowrap; + } + .query-group-cust{ + width: calc(50% - 15px); + min-width: 100px !important; + } + .query-group-split-cust{ + width: 30px; + display: inline-block; + text-align: center + } + } +</style> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi new file mode 100644 index 0000000..0ff2ed7 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi @@ -0,0 +1,90 @@ +import { defHttp } from "/@/utils/http/axios"; +import { Modal } from 'ant-design-vue'; + +enum Api { + list = '/${entityPackage}/${entityName?uncap_first}/rootList', + save='/${entityPackage}/${entityName?uncap_first}/add', + edit='/${entityPackage}/${entityName?uncap_first}/edit', + delete${entityName} = '/${entityPackage}/${entityName?uncap_first}/delete', + importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel', + exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls', + loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot', + getChildList = '/${entityPackage}/${entityName?uncap_first}/childList', + getChildListBatch = '/${entityPackage}/${entityName?uncap_first}/getChildListBatch', +} + +/** + * 导出api + * @param params + */ +export const getExportUrl = Api.exportXls; + +/** + * 导入api + * @param params + */ +export const getImportUrl = Api.importExcel; + +/** + * 列表接口 + * @param params + */ +export const list = (params) => defHttp.get({ url: Api.list, params }); + +/** + * 删除 + * @param params + * @param handleSuccess + */ +export const delete${entityName} = (params,handleSuccess) => { + return defHttp.delete({ url: Api.delete${entityName}, params }, { joinParamsToUrl: true }).then(() => { + handleSuccess(); + }); +} + +/** + * 批量删除 + * @param params + * @param handleSuccess + */ +export const batchDelete${entityName} = (params, handleSuccess) => { + Modal.confirm({ + title: '确认删除', + content: '是否删除选中数据', + okText: '确认', + cancelText: '取消', + onOk: () => { + return defHttp.delete({ url: Api.delete${entityName}, data: params }, { joinParamsToUrl: true }).then(() => { + handleSuccess(); + }); + } + }); +} + +/** + * 保存或者更新 + * @param params + * @param isUpdate + */ +export const saveOrUpdateDict = (params, isUpdate) => { + let url = isUpdate ? Api.edit : Api.save; + return defHttp.post({ url: url, params },{ isTransformResponse:false }); +} + +/** + * 查询全部树形节点数据 + * @param params + */ +export const loadTreeData = (params) => defHttp.get({ url: Api.loadTreeData,params }); + +/** + * 查询子节点数据 + * @param params + */ +export const getChildList = (params) => defHttp.get({ url: Api.getChildList, params }); + +/** + * 批量查询子节点数据 + * @param params + */ +export const getChildListBatch = (params) => defHttp.get({ url: Api.getChildListBatch, params },{ isTransformResponse:false }); diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi new file mode 100644 index 0000000..8a3ecb8 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi @@ -0,0 +1,399 @@ +<#include "/common/utils.ftl"> +import {BasicColumn} from '/@/components/Table'; +import {FormSchema} from '/@/components/Table'; +import { rules} from '/@/utils/helper/validator'; +import { render } from '/@/utils/common/renderUtils'; +//列表数据 +export const columns: BasicColumn[] = [ + <#list columns as po> + <#if po.isShowList =='Y' && po.fieldName !='id'> + { + title: '${po.filedComment}', + <#if po.fieldDbName == tableVo.extendParams.textField> + align: 'left', + <#else> + align: 'center', + </#if> + <#if po.sort=='Y'> + sorter: true, + </#if> + <#if po.classType=='date'> + dataIndex: '${po.fieldName}', + customRender:({text}) =>{ + return !text?"":(text.length>10?text.substr(0,10):text); + }, + <#elseif po.fieldDbType=='Blob'> + dataIndex: '${po.fieldName}String' + <#elseif po.classType=='umeditor'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'htmlSlot' }, + <#elseif po.classType=='pca'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'pcaSlot' }, + <#elseif po.classType=='file'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'fileSlot' }, + <#elseif po.classType=='image'> + dataIndex: '${po.fieldName}', + customRender: render.renderImage, + <#elseif po.classType=='switch'> + dataIndex: '${po.fieldName}', +<#assign switch_extend_arr=['Y','N']> +<#if po.dictField?default("")?contains("[")> +<#assign switch_extend_arr=po.dictField?eval> +</#if> +<#list switch_extend_arr as a> +<#if a_index == 0> +<#assign switch_extend_arr1=a> +<#else> +<#assign switch_extend_arr2=a> +</#if> +</#list> + customRender:({text}) => { + return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]); + }, + <#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'> + dataIndex: '${po.fieldName}_dictText' + <#elseif po.classType=='cat_tree'> + dataIndex: '${po.fieldName}', + <#if po.dictText?default("")?trim?length == 0> + customRender:({text}) => { + return render.renderCategoryTree(text,'${po.dictField?default("")}'); + }, + <#else> + customRender: ({text, record}) => (text ? record['${po.dictText}'] : ''); + </#if> + <#else> + dataIndex: '${po.fieldName}' + </#if> + }, + </#if> + </#list> +]; + +//查询数据 +export const searchFormSchema: FormSchema[] = [ +<#-- 开始循环 --> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.isQuery=='Y'> +<#assign query_flag=true> + <#assign query_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign query_field_dictCode="${po.dictField}"> + </#if> +<#if po.queryMode=='single'> + { + label: "${po.filedComment}", + field: "${po.fieldName}", +<#if po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps: { + dict:"${po.dictTable},${po.dictText},${po.dictField}" + }, +<#elseif po.classType=='sel_user'> + component: 'JSelectUserByDept', +<#elseif po.classType=='switch'> + component: 'JSwitch', + componentProps: { + <#if po.dictField != 'is_open'> + options: '${po.dictField}', + </#if> + }, + <#elseif po.classType=='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType=='list_multi'> + component: 'JSelectMultiple', + componentProps: { + <#if po.dictTable?default("")?trim?length gt 1> + options: "${po.dictField}", + dictCode: "${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode: "${po.dictField}", + </#if> + triggerChange: true + }, + <#elseif po.classType=='cat_tree'> + component: 'JCategorySelect', + componentProps:{ + pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题 + }, +<#elseif po.classType=='date'> + component: 'DatePicker', +<#elseif po.classType=='datetime'> + component: 'DatePicker', + componentProps: { + showTime: true + }, +<#elseif po.classType=='pca'> + component: 'JAreaLinkage', +<#elseif po.classType=='popup'> + <#include "/common/form/vue3popup.ftl"> +<#elseif po.classType == 'sel_tree'> + component: 'JTreeSelect', + componentProps: { + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict: "${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}", + </#if> + <#if po.dictText?split(',')[1]??> + pidField: "${po.dictText?split(',')[1]}", + </#if> + <#if po.dictText?split(',')[3]??> + hasChildField: "${po.dictText?split(',')[3]}", + </#if> + </#if> + pidValue: "${po.dictField}", + }, +<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> +<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> + component: 'JDictSelectTag', + componentProps:{ + <#if po.dictTable?default("")?trim?length gt 1> + dictCode: "${po.dictTable},${po.dictText},${po.dictField}" + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode: "${po.dictField}" + </#if> + }, +<#else> + component: 'Input', +</#if> + colProps: {span: 6}, + }, +<#else> + { + label: "${po.filedComment}", + field: "${po.fieldName}", +<#if po.classType=='date'> + component: 'RangePicker', +<#elseif po.classType=='datetime'> + component: 'RangePicker', + componentProps: { + showTime: true + }, +<#elseif po.classType == 'time'> + component: 'TimePicker', + componentProps:{ + valueFormat: 'HH:mm:ss', + }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', +<#else> + component: 'Input', //TODO 范围查询 +</#if> + colProps: {span: 6}, + }, +</#if> +</#if> +</#list> +<#-- 结束循环 --> +]; + +//表单数据 +export const formSchema: FormSchema[] = [ +<#assign form_cat_tree = false> +<#assign form_cat_back = ""> +<#assign bpm_flag=false> +<#assign id_exists = false> +<#list columns as po><#rt/> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.fieldDbName == 'id'> + <#assign id_exists = true> +</#if> +<#if po.isShow =='Y'> +<#assign form_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictField}"> + </#if> + { + label: '${po.filedComment}', + field: ${autoStringSuffix(po)}, + <#if po.fieldDbName == tableVo.extendParams.pidField> + component: 'JTreeSelect', + componentProps: { + dict: "${tableVo.tableName},${tableVo.extendParams.textField},id", + pidField: "${tableVo.extendParams.pidField}", + pidValue: "0", + hasChildField: "${tableVo.extendParams.hasChildren}", + }, + <#elseif po.classType =='date'> + component: 'DatePicker', + <#elseif po.classType =='datetime'> + component: 'DatePicker', + componentProps: { + showTime:true, + valueFormat: 'YYYY-MM-DD hh:mm:ss' + }, + <#elseif po.classType =='time'> + component: 'TimePicker', + componentProps:{ + valueFormat: 'HH:mm:ss', + }, + <#elseif po.classType =='popup'> + <#include "/common/form/vue3popup.ftl"> + <#elseif po.classType =='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType =='switch'> + component: 'JSwitch', + componentProps:{ + <#if po.dictField != 'is_open'> + options:${po.dictField} + </#if> + }, + <#elseif po.classType =='pca'> + component: 'JAreaLinkage', + <#elseif po.classType =='markdown'> + component: 'JMarkdownEditor',//注意string转换问题 + <#elseif po.classType =='password'> + component: 'InputPassword', + <#elseif po.classType =='sel_user'> + component: 'JSelectUserByDept', + componentProps:{ + labelKey: 'realname', + }, + <#elseif po.classType =='textarea'> + component: 'InputTextArea', + <#elseif po.classType=='list' || po.classType=='radio'> + component: 'JDictSelectTag', + componentProps:{ + dictCode: "${form_field_dictCode}" + }, + <#elseif po.classType=='list_multi' || po.classType=='checkbox'> + component: 'JSelectMultiple', + componentProps:{ + dictCode: "${form_field_dictCode}" + }, + <#elseif po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps:{ + dict: "${form_field_dictCode}" + }, +<#elseif po.classType=='cat_tree'> + <#assign form_cat_tree = true> + component: 'JCategorySelect', + componentProps:{ + pcode: "${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题 + }, + <#if po.dictText?default("")?trim?length gt 1> + <#assign form_cat_back = "${po.dictText}"> + </#if> + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'InputNumber', + <#elseif po.classType=='file'> + component: 'JUpload', + componentProps:{ + <#if po.uploadnum??> + maxCount: ${po.uploadnum} + </#if> + }, + <#elseif po.classType=='image'> + component: 'JImageUpload', + componentProps:{ + <#if po.uploadnum??> + fileMax: ${po.uploadnum} + </#if> + }, + <#elseif po.classType=='umeditor'> + component: 'JEditor', + <#elseif po.classType == 'sel_tree'> + component: 'JTreeSelect', + componentProps:{ + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict: "${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}", + </#if> + <#if po.dictText?split(',')[1]??> + pidField: "${po.dictText?split(',')[1]}", + </#if> + <#if po.dictText?split(',')[3]??> + hasChildField: "${po.dictText?split(',')[3]}", + </#if> + </#if> + pidValue: "${po.dictField}", + }, + <#else> + component: 'Input', + </#if> + <#include "/common/utils.ftl"> + <#if po.isShow == 'Y' && poHasCheck(po)> + dynamicRules: ({ model, schema }) => { + <#if po.fieldName != 'id'> + <#assign fieldValidType = po.fieldValidType!''> + return [ + <#-- 非空校验 --> + <#if po.nullable == 'N' || fieldValidType == '*'> + { required: true, message: '请输入${po.filedComment}!' }, + <#elseif fieldValidType!=''> + { required: false }, + </#if> + <#-- 唯一校验 --> + <#if fieldValidType == 'only'> + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, + <#-- 6到16位数字 --> + <#elseif fieldValidType == 'n6-16'> + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!' }, + <#-- 6到16位任意字符 --> + <#elseif fieldValidType == '*6-16'> + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!' }, + <#-- 6到18位字母 --> + <#elseif fieldValidType == 's6-18'> + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!' }, + <#-- 网址 --> + <#elseif fieldValidType == 'url'> + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!' }, + <#-- 电子邮件 --> + <#elseif fieldValidType == 'e'> + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件! }, + <#-- 手机号码 --> + <#elseif fieldValidType == 'm'> + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!' }, + <#-- 邮政编码 --> + <#elseif fieldValidType == 'p'> + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!' }, + <#-- 字母 --> + <#elseif fieldValidType == 's'> + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!' }, + <#-- 数字 --> + <#elseif fieldValidType == 'n'> + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!' }, + <#-- 整数 --> + <#elseif fieldValidType == 'z'> + { pattern: /^-?\d+$/, message: '请输入整数!' }, + <#-- 金额 --> + <#elseif fieldValidType == 'money'> + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!' }, + <#-- 正则校验 --> + <#elseif fieldValidType != '' && fieldValidType != '*'> + { pattern: '${fieldValidType}', message: '不符合校验规则!' }, + <#-- 无校验 --> + <#else> + <#t> + </#if> + ]; + </#if> + }, + </#if> + <#if po.readonly=='Y'> + dynamicDisabled: true + </#if> + }, +</#if> +</#list> +<#if id_exists == false> + // TODO 主键隐藏字段,目前写死为ID + { + label: '', + field: 'id', + component: 'Input', + show: false, + }, +</#if> +]; diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei new file mode 100644 index 0000000..a5b550f --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei @@ -0,0 +1,235 @@ +<#include "/common/utils.ftl"> +<template> + <a-spin :spinning="confirmLoading"> + <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-row> +<#assign need_category = false> +<#assign bpm_flag=false> +<#assign need_pca = false> +<#assign need_search = false> +<#assign need_dept_user = false> +<#assign need_switch = false> +<#assign need_dept = false> +<#assign need_multi = false> +<#assign need_popup = false> +<#assign need_select_tag = false> +<#assign need_select_tree = false> +<#assign need_time = false> +<#assign need_markdown = false> +<#assign need_upload = false> +<#assign need_image_upload = false> +<#assign need_editor = false> +<#assign need_checkbox = false> +<#assign pidFieldName = ""> +<#assign hasOnlyValidate = false> +<#assign form_span = 24> +<#if tableVo.fieldRowNum==2> +<#assign form_span = 12> +<#elseif tableVo.fieldRowNum==3> +<#assign form_span = 8> +<#elseif tableVo.fieldRowNum==4> +<#assign form_span = 6> +</#if> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + <#assign hasOnlyValidate = true> +</#if> + <#if po.fieldDbName == tableVo.extendParams.pidField> + <#assign pidFieldName = po.fieldName> + <a-col :span="${form_span}"> + <a-form-item label="父级节点" v-bind="validateInfos.${autoStringSuffixForModel(po)}"> + <j-tree-select + placeholder="请选择${po.filedComment}" + v-model:value="formData.${po.fieldName}" + dict="${tableVo.tableName},${tableVo.extendParams.textField},id" + pidField="${tableVo.extendParams.pidField}" + pidValue="0" + hasChildField="${tableVo.extendParams.hasChildren}" + <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>> + </j-tree-select> + </a-form-item> + </a-col> + </#if> + <#include "/common/form/native/vue3NativeForm.ftl"> +</#list> + </a-row> + </a-form> + </a-spin> +</template> + +<script lang="ts" setup> + import { ref, reactive, defineExpose, nextTick, unref, defineProps, computed } from 'vue'; + import { defHttp } from '/@/utils/http/axios'; + import { useMessage } from '/@/hooks/web/useMessage'; + import moment from 'moment'; + <#include "/common/form/native/vue3NativeImport.ftl"> + import { getValueType } from '/@/utils'; + import { validateDuplicateValue } from '/@/utils/helper/validator'; + import {loadTreeData, saveOrUpdateDict} from '../${entityName}.api'; + import { Form } from 'ant-design-vue'; + <#if hasOnlyValidate == true> + import { duplicateValidate } from '/@/utils/helper/validator' + </#if> + + const useForm = Form.useForm; + const formRef = ref(); + const isUpdate = ref(true); + const expandedRowKeys = ref([]); + const treeData = ref([]); + const pidField = ref<string>('pid'); + const emit = defineEmits(['register', 'ok']); + let model: Nullable<Recordable> = null; + const formData = reactive<Record<string, any>>({ +<#list columns as po> + <#if po.isShow == 'Y'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ${po.fieldName}: undefined, + <#elseif po.fieldDbType=='Blob'> + ${po.fieldName}String: '', + <#else> + ${po.fieldName}: '', + </#if> + </#if> +</#list> + }); + const { createMessage } = useMessage(); + const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } }); + const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } }); + const confirmLoading = ref<boolean>(false); + //表单验证 + const validatorRules = { + <#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl"> + }; + const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true }); + const props = defineProps({ + disabled: { type: Boolean, default: false }, + }); + + /** + * 新增 + */ + function add(obj = {}) { + edit(obj); + } + + /** + * 编辑 + */ + function edit(record) { + nextTick(async () => { + resetFields(); + expandedRowKeys.value = []; + treeData.value = await loadTreeData({ async: false, pcode: '' }); + //赋值 + Object.assign(formData, record); + }); + } + + /** + * 根据pid获取展开的节点 + * @param pid + * @param arr + */ + function getExpandKeysByPid(pid, arr) { + if (pid && arr && arr.length > 0) { + for (let i = 0; i < arr.length; i++) { + if (arr[i].key == pid && unref(expandedRowKeys).indexOf(pid) < 0) { + expandedRowKeys.value.push(arr[i].key); + getExpandKeysByPid(arr[i]['parentId'], unref(treeData)); + } else { + getExpandKeysByPid(pid, arr[i].children); + } + } + } + } + + /** + * 提交数据 + */ + async function submitForm() { + // 触发表单验证 + await validate(); + confirmLoading.value = true; + const isUpdate = ref<boolean>(false); + //时间格式化 + if (formData.id) { + isUpdate.value = true; + } + //循环数据 + for (let data in formData) { + //如果该数据是数组并且是字符串类型 + if (formData[data] instanceof Array) { + let valueType = getValueType(formRef.value.getProps, data); + //如果是字符串类型的需要变成以逗号分割的字符串 + if (valueType === 'string') { + formData[data] = formData[data].join(','); + } + } + } + await saveOrUpdateDict(formData, isUpdate.value) + .then(async (res) => { + if (res.success) { + await getExpandKeysByPid(formData['${pidFieldName}'], unref(treeData)); + emit('ok', { + isUpdate: unref(isUpdate), + values: { ...formData }, + expandedArr: unref(expandedRowKeys).reverse(), + // 是否更改了父级节点 + changeParent: model != null && model['${pidFieldName}'] != formData['${pidFieldName}'], + }); + createMessage.success(res.message); + } else { + createMessage.warning(res.message); + } + }) + .finally(() => { + confirmLoading.value = false; + }); + } + + <#if need_popup> + /** + * popup组件值改变事件 + */ + function setFieldsValue(map) { + Object.keys(map).map((key) => { + formData[key] = map[key]; + }); + } + </#if> + + <#if need_category || need_select_tree> + /** + * 值改变事件触发 + * @param key + * @param value + */ + function handleFormChange(key, value) { + formData[key] = value; + } + </#if> + + <#list columns as po> + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + async function ${po.fieldName}Duplicatevalidate(_r, value) { + return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '') + } + </#if> + </#list> + defineExpose({ + add, + edit, + submitForm, + }); +</script> + +<style lang="less" scoped> + .antd-modal-form { + height: 500px !important; + overflow-y: auto; + padding: 24px 24px 24px 24px; + } +</style> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei new file mode 100644 index 0000000..70dfb5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei @@ -0,0 +1,81 @@ +<template> + <a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭"> + <${entityName}Form ref="registerForm" @ok="submitCallback" :disabled="disableSubmit"></${entityName}Form> + </a-modal> +</template> + +<script lang="ts" setup> + import { ref, nextTick, defineExpose } from 'vue'; + import ${entityName}Form from './${entityName}Form.vue' + + const title = ref<string>(''); + const width = ref<number>(800); + const visible = ref<boolean>(false); + const disableSubmit = ref<boolean>(false); + const registerForm = ref(); + const emit = defineEmits(['register', 'success']); + + /** + * 新增 + */ + function add(obj={}) { + title.value = '新增'; + visible.value = true; + nextTick(() => { + registerForm.value.add(obj); + }); + } + + /** + * 编辑 + * @param record + */ + function edit(record) { + title.value = disableSubmit.value ? '详情' : '编辑'; + visible.value = true; + nextTick(() => { + registerForm.value.edit(record); + }); + } + + /** + * 确定按钮点击事件 + */ + function handleOk() { + registerForm.value.submitForm(); + } + + /** + * form保存回调事件 + */ + function submitCallback({ isUpdate, values, expandedArr, changeParent }) { + handleCancel(); + emit('success', { + isUpdate: isUpdate, + values: values, + expandedArr: expandedArr, + // 是否更改了父级节点 + changeParent: changeParent, + }); + } + + /** + * 取消按钮回调事件 + */ + function handleCancel() { + visible.value = false; + } + + defineExpose({ + add, + edit, + disableSubmit, + }); +</script> + +<style> + /**隐藏样式-modal确定按钮 */ + .jee-hidden { + display: none !important; + } +</style> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index 7bf649a..9196325 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai index d549c98..03fe3eb 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as subTab> #segment#${subTab.entityName}.java package ${bussiPackage}.${entityPackage}.entity; @@ -65,7 +66,8 @@ public class ${subTab.entityName} implements Serializable { @Dict(dicCode = "id",dicText = "name",dictTable = "sys_category") </#if> <#if po.classType =='sel_depart'> - @Dict(dicCode = "id",dicText = "depart_name",dictTable = "sys_depart") + <#assign list_field_dictCode='dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dictTable = "sys_depart"'> + @Dict(${list_field_dictCode}) </#if> <#-- 大字段转换 --> <#include "/common/blob.ftl"> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei index 1cf248a..494ff9f 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -193,7 +193,7 @@ <#assign sub_seq=1> <#list subTables as sub> <a-tab-pane tab="${sub.ftlDescription}" key="${sub_seq}" <#if sub_seq gt 1>forceRender</#if>> - <${sub.entityName}List :mainId="selectedMainId" /> + <${sub.entityName}List :mainId="${sub.entityName?uncap_first}MainId" /> </a-tab-pane> <#assign sub_seq=sub_seq+1> </#list> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei index 120bdd0..1df9859 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -44,7 +44,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -54,7 +54,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei index 1af2447..37a1a11 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei @@ -46,7 +46,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}"multi <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}"<#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -56,7 +56,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}"placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}"<#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index 9aa4df2..45f4359 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -46,6 +46,10 @@ <template #htmlSlot="{text}"> <div v-html="text"></div> </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> <template #fileSlot="{text}"> <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> @@ -77,6 +81,10 @@ </#list> import {columns, searchFormSchema} from './${entityName}.data'; import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; + import {downloadFile} from '/@/utils/common/renderUtils'; + <#if list_need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; + </#if> <#if list_need_category> import { loadCategoryData } from '/@/api/common/api' import { getAuthCache, setAuthCache } from '/@/utils/auth'; @@ -94,6 +102,17 @@ rowSelection: {type: 'radio'}, formConfig: { schemas: searchFormSchema, + fieldMapToNumber: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']], + </#if> + </#if> + </#if> + </#list> + ], fieldMapToTime: [ <#list columns as po> <#if po.isQuery=='Y'> @@ -108,14 +127,15 @@ </#list> ], }, - actionColumn: { + actionColumn: { width: 120, - }, - pagination:{ - current: 1, - pageSize: 5, - pageSizeOptions: ['5', '10', '20'], - } + fixed:'right' + }, + pagination:{ + current: 1, + pageSize: 5, + pageSizeOptions: ['5', '10', '20'], + } }, exportConfig: { name:"${tableVo.ftlDescription}", diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index 19bf9d3..47f36da 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> import {BasicColumn} from '/@/components/Table'; import {FormSchema} from '/@/components/Table'; import { rules} from '/@/utils/helper/validator'; @@ -24,7 +25,7 @@ export const columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -91,17 +92,23 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='switch'> component: 'JSwitch', componentProps:{ + query:true, <#if po.dictField != 'is_open'> - options:"${po.dictField}" + options:${po.dictField} </#if> }, <#elseif po.classType=='sel_depart'> component: 'JSelectDept', <#elseif po.classType=='list_multi'> - component: 'JMultiSelectTag',//暂无该组件 + component: 'JSelectMultiple', componentProps:{ - dictCode:"query_field_dictCode?default("")" - }, + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true + }, <#elseif po.classType=='cat_tree'> component: 'JCategorySelect', componentProps:{ @@ -117,16 +124,7 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='pca'> component: 'JAreaLinkage', <#elseif po.classType=='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:"${po.dictField}", - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> component: 'JDictSelectTag', @@ -153,6 +151,8 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', <#else> component: 'Input', //TODO 范围查询 </#if> @@ -186,27 +186,22 @@ export const formSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -235,7 +230,7 @@ export const formSchema: FormSchema[] = [ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -270,7 +265,7 @@ export const formSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -302,16 +297,16 @@ export const formSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -387,7 +382,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -419,7 +414,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -452,27 +447,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -494,14 +484,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -536,7 +526,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -568,16 +558,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/[1-n]List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/[1-n]List.vuei index ceb367b..a7b39a7 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/[1-n]List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/[1-n]List.vuei @@ -51,6 +51,7 @@ import {${sub.entityName?uncap_first}List, ${sub.entityName?uncap_first}Delete, ${sub.entityName?uncap_first}DeleteBatch, ${sub.entityName?uncap_first}ExportXlsUrl, ${sub.entityName?uncap_first}ImportUrl } from './${entityName}.api'; import {isEmpty} from "/@/utils/is"; import {useMessage} from '/@/hooks/web/useMessage'; + import {downloadFile} from '/@/utils/common/renderUtils'; //接收主表id const mainId = inject('mainId') || ''; diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei index fd54ae4..9d11f25 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei @@ -1,5 +1,6 @@ +<#include "/common/utils.ftl"> <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> <BasicForm @register="registerForm"/> </BasicModal> </template> @@ -18,6 +19,7 @@ labelWidth: 150, schemas: formSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); //表单赋值 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { @@ -54,5 +56,12 @@ </script> <style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + :deep(.ant-calendar-picker){ + width: 100% + } </style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Modal.vuei index a328e79..d2ea771 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Modal.vuei @@ -2,7 +2,7 @@ <#list subTables as sub> #segment#${sub.entityName}Modal.vue <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> <BasicForm @register="registerForm"/> </BasicModal> </template> @@ -24,6 +24,7 @@ labelWidth: 150, schemas: ${sub.entityName?uncap_first}FormSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); //表单赋值 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { @@ -63,4 +64,14 @@ } } </script> +<style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + + :deep(.ant-calendar-picker){ + width: 100% + } +</style> </#list> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai index 36fb9fc..579ab5f 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -200,17 +200,14 @@ public class ${entityName}Controller { QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - //Step.2 获取导出数据 - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); - // 过滤选中数据 + //配置选中数据查询条件 String selections = request.getParameter("selections"); - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); - if(oConvertUtils.isEmpty(selections)) { - ${entityName?uncap_first}List = queryList; - }else { - List<String> selectionList = Arrays.asList(selections.split(",")); - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + if(oConvertUtils.isNotEmpty(selections)) { + List<String> selectionList = Arrays.asList(selections.split(",")); + queryWrapper.in("id",selectionList); } + //Step.2 获取导出数据 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper); // Step.3 组装pageList List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index ed071ad..ee8d8cc 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai index 30ba2dd..bca19fd 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as subTab> #segment#${subTab.entityName}.java package ${bussiPackage}.${entityPackage}.entity; @@ -33,9 +34,9 @@ public class ${subTab.entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei index ad814c0..74784e9 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -41,7 +41,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -51,7 +51,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-decorator="[${autoStringSuffix(po)}${autoWriteRules(po)}]" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei index 4252c92..96d9559 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -36,9 +36,9 @@ <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" /> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" /> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index 23fe713..a62d4fb 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -60,6 +60,10 @@ <template #htmlSlot="{text}"> <div v-html="text"></div> </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> <template #fileSlot="{text}"> <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> @@ -81,6 +85,10 @@ </#list> import {columns, searchFormSchema} from './${entityName}.data'; import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; + import {downloadFile} from '/@/utils/common/renderUtils'; + <#if list_need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; + </#if> <#if list_need_category> import { loadCategoryData } from '/@/api/common/api' import { getAuthCache, setAuthCache } from '/@/utils/auth'; @@ -102,6 +110,17 @@ schemas: searchFormSchema, autoSubmitOnEnter:true, showAdvancedButton:true, + fieldMapToNumber: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']], + </#if> + </#if> + </#if> + </#list> + ], fieldMapToTime: [ <#list columns as po> <#if po.isQuery=='Y'> @@ -116,9 +135,10 @@ </#list> ], }, - actionColumn: { + actionColumn: { width: 120, - }, + fixed:'right' + }, }, exportConfig: { name:"${tableVo.ftlDescription}", diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index a8f8224..cecb7bf 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> import {BasicColumn} from '/@/components/Table'; import {FormSchema} from '/@/components/Table'; import { rules} from '/@/utils/helper/validator'; @@ -25,7 +26,7 @@ export const columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -57,7 +58,7 @@ export const columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -84,7 +85,7 @@ export const searchFormSchema: FormSchema[] = [ <#if po.queryMode=='single'> { label: "${po.filedComment}", - field: "${po.fieldName}", + field: ${autoStringSuffix(po)}, <#if po.classType=='sel_search'> component: 'JSearchSelect', componentProps:{ @@ -95,16 +96,22 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='switch'> component: 'JSwitch', componentProps:{ + query:true, <#if po.dictField != 'is_open'> - options:"${po.dictField}" + options:${po.dictField} </#if> }, <#elseif po.classType=='sel_depart'> component: 'JSelectDept', <#elseif po.classType=='list_multi'> - component: 'JMultiSelectTag',//暂无该组件 - componentProps:{ - dictCode:"query_field_dictCode?default("")" + component: 'JSelectMultiple', + componentProps:{ + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true }, <#elseif po.classType=='cat_tree'> component: 'JCategorySelect', @@ -121,16 +128,7 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='pca'> component: 'JAreaLinkage', <#elseif po.classType=='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:"${po.dictField}", - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> component: 'JDictSelectTag', @@ -157,6 +155,8 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', <#else> component: 'Input', //TODO 范围查询 </#if> @@ -189,28 +189,23 @@ export const formSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, - <#elseif po.classType =='sel_depart'> + <#include "/common/form/vue3popup.ftl"> + <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> component: 'JSwitch', @@ -231,14 +226,14 @@ export const formSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -273,7 +268,7 @@ export const formSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -305,16 +300,16 @@ export const formSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern:/^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -390,7 +385,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -422,7 +417,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -436,10 +431,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ <#assign form_cat_tree = false> <#assign form_cat_back = ""> <#assign bpm_flag=false> +<#assign sub_id_exists=false> <#list sub.colums as po><#rt/> <#if po.fieldDbName=='bpm_status'> <#assign bpm_flag=true> </#if> +<#if po.fieldDbName=='id'> + <#assign sub_id_exists=true> +</#if> <#if po.isShow =='Y'> <#assign form_field_dictCode=""> <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> @@ -449,27 +448,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -491,14 +485,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -533,7 +527,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -565,16 +559,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -616,6 +610,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ }, </#if> </#list> +<#if sub_id_exists == false> + { + label: '', + field: 'id', + component: 'Input', + show: false + }, +</#if> ]; </#if> </#list> @@ -642,12 +644,20 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ <#if col.readonly=='Y'> disabled:true, </#if> +<#elseif col.classType =='time'> + type: JVxeTypes.time, + <#if col.readonly=='Y'> + disabled:true, + </#if> <#elseif col.classType =='textarea'> type: JVxeTypes.textarea, <#if col.readonly=='Y'> disabled:true, </#if> -<#elseif "int,decimal,double,"?contains(col.classType)> +<#-- update-begin-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> +<#-- elseif "int,decimal,double,"?contains(col.classType) --> +<#elseif col.fieldDbType=='int' || col.fieldDbType=='double' || col.fieldDbType=='BigDecimal'> +<#-- update-end-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> type: JVxeTypes.inputNumber, <#if col.readonly=='Y'> disabled:true, @@ -684,6 +694,16 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ <#if col.readonly=='Y'> disabled:true, </#if> +<#elseif col.classType =='sel_depart'> + type: JVxeTypes.departSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='sel_user'> + type: JVxeTypes.userSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> <#elseif col.classType =='image'> type: JVxeTypes.image, token:true, @@ -707,9 +727,9 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ <#elseif col.classType =='switch'> type: JVxeTypes.checkbox, <#if col.dictField == 'is_open'> - customValue: ['Y', 'N'], + customValue: ['Y', 'N'], <#else> - customValue: ${col.dictField}, + customValue: ${col.dictField}, </#if> <#if col.readonly=='Y'> disabled:true, @@ -720,18 +740,11 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ <#else> <#assign popupBackFields = "${col.dictText}"> </#if> - type: JVxeTypes.popup, - popupCode:"${col.dictTable}", - field:"${col.dictField}", - orgFields:"${col.dictField}", - destFields:"${Format.underlineToHump(col.dictText)}", - <#if col.readonly=='Y'> - disabled:true, - </#if> + <#include "/common/form/vue3Jvxepopup.ftl"> <#else> - type: JVxeTypes.input, + type: JVxeTypes.input, <#if col.readonly=='Y'> - disabled:true, + disabled:true, </#if> </#if> <#if col.classType =='list_multi' || col.classType =='checkbox'> @@ -754,18 +767,7 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [ defaultValue:'', </#if> <#-- 子表的校验 --> -<#assign subFieldValidType = col.fieldValidType!''> -<#-- 非空校验 --> -<#if col.nullable == 'N' || subFieldValidType == '*'> - validateRules: [{ required: true, message: '${'$'}{title}不能为空' }], -<#-- 其他情况下,只要有值就被认为是正则校验 --> -<#elseif subFieldValidType?length gt 0> -<#assign subMessage = '格式不正确'> -<#if subFieldValidType == 'only' > - <#assign subMessage = '不能重复'> -</#if> - validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }], -</#if> + <#include "/common/validatorRulesTemplate/sub-vue3.ftl"> }, </#if> </#if> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei index 4996cb5..b641c5d 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei @@ -1,5 +1,6 @@ +<#include "/common/utils.ftl"> <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> <BasicForm @register="registerForm" ref="formRef"/> <!-- 子表单区域 --> <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs"> @@ -7,7 +8,7 @@ <#assign refKey = sub.entityName?uncap_first/> <#if sub.foreignRelationType =='1'> <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true"> - <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form"></${sub.entityName}Form> + <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form" :disabled="formDisabled"></${sub.entityName}Form> </a-tab-pane> <#else> @@ -19,7 +20,8 @@ :loading="${sub.entityName?uncap_first}Table.loading" :columns="${sub.entityName?uncap_first}Table.columns" :dataSource="${sub.entityName?uncap_first}Table.dataSource" - :maxHeight="300" + :height="340" + :disabled="formDisabled" :rowNumber="true" :rowSelection="true" :toolbar="true" @@ -48,6 +50,7 @@ // Emits声明 const emit = defineEmits(['register','success']); const isUpdate = ref(true); + const formDisabled = ref(false); const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]); <#assign hasOne2Many = false> <#assign hasOne2One = false> @@ -77,6 +80,7 @@ labelWidth: 150, schemas: formSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); //表单赋值 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { @@ -84,6 +88,7 @@ await reset(); setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter}); isUpdate.value = !!data?.isUpdate; + formDisabled.value = !data?.showFooter; if (unref(isUpdate)) { //表单赋值 await setFieldsValue({ @@ -176,5 +181,12 @@ </script> <style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + :deep(.ant-calendar-picker){ + width: 100% + } </style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei index 062fa1b..37dde1f 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as sub> <#if sub.foreignRelationType=='1'> #segment#${sub.entityName}Form.vue @@ -15,11 +16,18 @@ name:"${sub.entityName}Form", components: {BasicForm}, emits:['register'], - setup(_,{emit}) { - const [registerForm, {resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({ + props:{ + disabled: { + type: Boolean, + default: false + } + }, + setup(props,{emit}) { + const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({ labelWidth: 150, schemas: ${sub.entityName?uncap_first}FormSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); /** *初始化加载数据 @@ -30,13 +38,22 @@ res.success && setFieldsValue({...res.result.records[0]}); }) } + setProps({disabled: props.disabled}) } - /** - *获取表单数据 - */ + + /** + *获取表单数据 + */ function getFormData(){ - return [getFieldsValue()]; + let formData = getFieldsValue(); + Object.keys(formData).map(k=>{ + if(formData[k] instanceof Array){ + formData[k] = formData[k].join(',') + } + }); + return [formData]; } + /** *表单校验 */ diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai index 43919c8..f9e34db 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -205,17 +205,14 @@ public class ${entityName}Controller { QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - //Step.2 获取导出数据 - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); - // 过滤选中数据 + //配置选中数据查询条件 String selections = request.getParameter("selections"); - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); - if(oConvertUtils.isEmpty(selections)) { - ${entityName?uncap_first}List = queryList; - }else { - List<String> selectionList = Arrays.asList(selections.split(",")); - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + if(oConvertUtils.isNotEmpty(selections)) { + List<String> selectionList = Arrays.asList(selections.split(",")); + queryWrapper.in("id",selectionList); } + //Step.2 获取导出数据 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper); // Step.3 组装pageList List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index c861c4a..4d1b425 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai index b6aabe8..93ddf95 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as subTab> #segment#${subTab.entityName}.java package ${bussiPackage}.${entityPackage}.entity; @@ -32,9 +33,9 @@ public class ${subTab.entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei index f387f76..51b96c7 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -48,7 +48,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -58,7 +58,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei index 96cfc11..97d1203 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -44,7 +44,7 @@ :multi="${po.extendParams.popupMulti?c}" @input="popupCallback"/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch> <#elseif po.classType =='pca'> @@ -54,7 +54,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}"/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index b75bbbd..b8cfe02 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -46,6 +46,10 @@ <template #htmlSlot="{text}"> <div v-html="text"></div> </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> <template #fileSlot="{text}"> <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> @@ -64,6 +68,10 @@ import ${entityName}Modal from './components/${entityName}Modal.vue' import {columns, searchFormSchema} from './${entityName}.data'; import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; + import {downloadFile} from '/@/utils/common/renderUtils'; +<#if list_need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; +</#if> <#if list_need_category> import { loadCategoryData } from '/@/api/common/api' import { getAuthCache, setAuthCache } from '/@/utils/auth'; @@ -84,6 +92,17 @@ schemas: searchFormSchema, autoSubmitOnEnter:true, showAdvancedButton:true, + fieldMapToNumber: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']], + </#if> + </#if> + </#if> + </#list> + ], fieldMapToTime: [ <#list columns as po> <#if po.isQuery=='Y'> @@ -98,9 +117,10 @@ </#list> ], }, - actionColumn: { + actionColumn: { width: 120, - }, + fixed:'right' + }, }, exportConfig: { name:"${tableVo.ftlDescription}", diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index c52445a..bb4097f 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> import {BasicColumn} from '/@/components/Table'; import {FormSchema} from '/@/components/Table'; import { rules} from '/@/utils/helper/validator'; @@ -25,7 +26,7 @@ export const columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -57,7 +58,7 @@ export const columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -95,16 +96,22 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='switch'> component: 'JSwitch', componentProps:{ + query:true, <#if po.dictField != 'is_open'> - options:"${po.dictField}" + options:${po.dictField} </#if> }, <#elseif po.classType=='sel_depart'> component: 'JSelectDept', <#elseif po.classType=='list_multi'> - component: 'JMultiSelectTag',//暂无该组件 + component: 'JSelectMultiple', componentProps:{ - dictCode:"query_field_dictCode?default("")" + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true }, <#elseif po.classType=='cat_tree'> component: 'JCategorySelect', @@ -121,16 +128,7 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='pca'> component: 'JAreaLinkage', <#elseif po.classType=='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:"${po.dictField}", - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> component: 'JDictSelectTag', @@ -157,6 +155,8 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', <#else> component: 'Input', //TODO 范围查询 </#if> @@ -189,27 +189,22 @@ export const formSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -231,14 +226,14 @@ export const formSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -273,7 +268,7 @@ export const formSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -305,16 +300,16 @@ export const formSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -373,10 +368,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ <#assign form_cat_tree = false> <#assign form_cat_back = ""> <#assign bpm_flag=false> +<#assign sub_id_exists=false> <#list sub.colums as po><#rt/> <#if po.fieldDbName=='bpm_status'> <#assign bpm_flag=true> </#if> +<#if po.fieldDbName=='id'> + <#assign sub_id_exists=true> +</#if> <#if po.isShow =='Y'> <#assign form_field_dictCode=""> <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> @@ -386,27 +385,22 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -428,14 +422,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" } @@ -470,7 +464,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -502,16 +496,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -553,6 +547,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ }, </#if> </#list> +<#if sub_id_exists == false> + { + label: '', + field: 'id', + component: 'Input', + show: false + }, +</#if> ]; </#if> </#list> @@ -579,12 +581,20 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#if col.readonly=='Y'> disabled:true, </#if> +<#elseif col.classType =='time'> + type: JVxeTypes.time, + <#if col.readonly=='Y'> + disabled:true, + </#if> <#elseif col.classType =='textarea'> type: JVxeTypes.textarea, <#if col.readonly=='Y'> disabled:true, </#if> -<#elseif "int,decimal,double,"?contains(col.classType)> +<#-- update-begin-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> +<#-- elseif "int,decimal,double,"?contains(col.classType) --> +<#elseif col.fieldDbType=='int' || col.fieldDbType=='double' || col.fieldDbType=='BigDecimal'> +<#-- update-end-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> type: JVxeTypes.inputNumber, <#if col.readonly=='Y'> disabled:true, @@ -621,6 +631,16 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#if col.readonly=='Y'> disabled:true, </#if> +<#elseif col.classType =='sel_depart'> + type: JVxeTypes.departSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='sel_user'> + type: JVxeTypes.userSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> <#elseif col.classType =='image'> type: JVxeTypes.image, token:true, @@ -644,9 +664,9 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#elseif col.classType =='switch'> type: JVxeTypes.checkbox, <#if col.dictField == 'is_open'> - customValue: ['Y', 'N'], + customValue: ['Y', 'N'], <#else> - customValue: ${col.dictField}, + customValue: ${col.dictField}, </#if> <#if col.readonly=='Y'> disabled:true, @@ -657,18 +677,11 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#else> <#assign popupBackFields = "${col.dictText}"> </#if> - type: JVxeTypes.popup, - popupCode:"${col.dictTable}", - field:"${col.dictField}", - orgFields:"${col.dictField}", - destFields:"${Format.underlineToHump(col.dictText)}", - <#if col.readonly=='Y'> - disabled:true, - </#if> + <#include "/common/form/vue3Jvxepopup.ftl"> <#else> - type: JVxeTypes.input, + type: JVxeTypes.input, <#if col.readonly=='Y'> - disabled:true, + disabled:true, </#if> </#if> <#if col.classType =='list_multi' || col.classType =='checkbox'> @@ -691,18 +704,7 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ defaultValue:'', </#if> <#-- 子表的校验 --> -<#assign subFieldValidType = col.fieldValidType!''> -<#-- 非空校验 --> -<#if col.nullable == 'N' || subFieldValidType == '*'> - validateRules: [{ required: true, message: '${'$'}{title}不能为空' }], -<#-- 其他情况下,只要有值就被认为是正则校验 --> -<#elseif subFieldValidType?length gt 0> -<#assign subMessage = '格式不正确'> -<#if subFieldValidType == 'only' > - <#assign subMessage = '不能重复'> -</#if> - validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }], -</#if> + <#include "/common/validatorRulesTemplate/sub-vue3.ftl"> }, </#if> </#if> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql new file mode 100644 index 0000000..7292339 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei index 6a2e26b..85ffc47 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei @@ -1,5 +1,6 @@ +<#include "/common/utils.ftl"> <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> <BasicForm @register="registerForm" ref="formRef"/> <!-- 子表单区域 --> <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs"> @@ -7,7 +8,7 @@ <#assign refKey = sub.entityName?uncap_first/> <#if sub.foreignRelationType =='1'> <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true"> - <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form"></${sub.entityName}Form> + <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form" :disabled="formDisabled"></${sub.entityName}Form> </a-tab-pane> <#else> @@ -19,9 +20,10 @@ :loading="${sub.entityName?uncap_first}Table.loading" :columns="${sub.entityName?uncap_first}Table.columns" :dataSource="${sub.entityName?uncap_first}Table.dataSource" - :maxHeight="300" + :height="340" :rowNumber="true" :rowSelection="true" + :disabled="formDisabled" :toolbar="true" /> </a-tab-pane> @@ -48,6 +50,7 @@ // Emits声明 const emit = defineEmits(['register','success']); const isUpdate = ref(true); + const formDisabled = ref(false); const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]); <#assign hasOne2Many = false> <#assign hasOne2One = false> @@ -77,6 +80,7 @@ labelWidth: 150, schemas: formSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); //表单赋值 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { @@ -84,6 +88,7 @@ await reset(); setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter}); isUpdate.value = !!data?.isUpdate; + formDisabled.value = !data?.showFooter; if (unref(isUpdate)) { //表单赋值 await setFieldsValue({ @@ -176,5 +181,12 @@ </script> <style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + :deep(.ant-calendar-picker){ + width: 100% + } </style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei index 6af0c52..dbb8c09 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as sub> <#if sub.foreignRelationType=='1'> #segment#${sub.entityName}Form.vue @@ -15,11 +16,18 @@ name:"${sub.entityName}Form", components: {BasicForm}, emits:['register'], - setup(_,{emit}) { - const [registerForm, {resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({ + props:{ + disabled: { + type: Boolean, + default: false + } + }, + setup(props,{emit}) { + const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({ labelWidth: 150, schemas: ${sub.entityName?uncap_first}FormSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); /** *初始化加载数据 @@ -30,12 +38,19 @@ res.success && setFieldsValue({...res.result[0]}); }) } + setProps({disabled: props.disabled}) } /** *获取表单数据 */ function getFormData(){ - return [getFieldsValue()]; + let formData = getFieldsValue(); + Object.keys(formData).map(k=>{ + if(formData[k] instanceof Array){ + formData[k] = formData[k].join(',') + } + }); + return [formData]; } /** *表单校验 diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei new file mode 100644 index 0000000..75691fc --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}List.vuei @@ -0,0 +1,340 @@ +<template> + <div> + <#assign query_field_no=0> + <#assign need_category = false> + <#assign need_pca = false> + <#assign need_search = false> + <#assign need_dept_user = false> + <#assign need_switch = false> + <#assign need_dept = false> + <#assign need_multi = false> + <#assign need_popup = false> + <#assign need_select_tag = false> + <#assign need_select_tree = false> + <#assign need_time = false> + <#assign bpm_flag=false> + <#assign need_markdown = false> + <#assign need_upload = false> + <#assign need_image_upload = false> + <#assign need_editor = false> + <#assign need_checkbox = false> + <!--查询区域--> + <div class="jeecg-basic-table-form-container"> + <a-form @keyup.enter.native="reload" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol"> + <a-row :gutter="24"> + <#-- 开始循环 --> + <#list columns as po> + <#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + </#if> + <#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0> + <#assign need_category=true> + </#if> + <#if po.classType=='pca'> + <#assign need_pca=true> + </#if> + <#if po.classType=='sel_search'> + <#assign need_search = true> + </#if> + <#if po.classType=='sel_user'> + <#assign need_dept_user = true> + </#if> + <#if po.classType=='sel_depart'> + <#assign need_dept = true> + </#if> + <#if po.classType=='switch'> + <#assign need_switch = true> + </#if> + <#if po.classType=='list_multi'> + <#assign need_multi = true> + </#if> + <#if po.classType=='popup'> + <#assign need_popup = true> + </#if> + <#if po.classType=='sel_tree'> + <#assign need_select_tree = true> + </#if> + <#if po.classType=='time'> + <#assign need_time = true> + </#if> + <#include "/common/form/native/vue3NativeSearch.ftl"> + </#list> + <#if query_field_no gt 2> + </template> +</#if> +<#if query_flag> + <a-col :xl="6" :lg="7" :md="8" :sm="24"> + <span style="float: left; overflow: hidden" class="table-page-search-submitButtons"> + <a-col :lg="6"> + <a-button type="primary" preIcon="ant-design:search-outlined" @click="reload">查询</a-button> + <a-button preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button> + <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px"> + {{ toggleSearchStatus ? '收起' : '展开' }} + <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" /> + </a> + </a-col> + </span> + </a-col> +</#if> + </a-row> + </a-form> + </div> +<#-- 结束循环 --> + <!--引用表格--> + <BasicTable @register="registerTable" :rowSelection="rowSelection"> + <!--插槽:table标题--> + <template #tableTitle> + <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button> + <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button> + <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> + <a-dropdown v-if="selectedRowKeys.length > 0"> + <template #overlay> + <a-menu> + <a-menu-item key="1" @click="batchHandleDelete"> + <Icon icon="ant-design:delete-outlined"></Icon> + 删除 + </a-menu-item> + </a-menu> + </template> + <a-button>批量操作 + <Icon icon="mdi:chevron-down"></Icon> + </a-button> + </a-dropdown> + </template> + <!--操作栏--> + <template #action="{ record }"> + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/> + </template> + <!--字段回显插槽--> + <template #htmlSlot="{text}"> + <div v-html="text"></div> + </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> + <template #fileSlot="{text}"> + <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> + </template> + </BasicTable> + <!-- 表单区域 --> + <${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal> + </div> +</template> + +<script lang="ts" name="${entityPackage}-${entityName?uncap_first}" setup> + import {ref, reactive, computed, unref} from 'vue'; + import {BasicTable, useTable, TableAction} from '/@/components/Table'; + import { useListPage } from '/@/hooks/system/useListPage' + import {useModal} from '/@/components/Modal'; + import ${entityName}Modal from './components/${entityName}Modal.vue' + import {columns, searchFormSchema} from './${entityName}.data'; + import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; + import {downloadFile} from '/@/utils/common/renderUtils'; + <#include "/common/form/native/vue3NativeImport.ftl"> +<#if need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; +</#if> + <#if need_category> + import { loadCategoryData } from '/@/api/common/api' + import { getAuthCache, setAuthCache } from '/@/utils/auth'; + import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum'; + </#if> + const checkedKeys = ref<Array<string | number>>([]); + //注册model + const [registerModal, {openModal}] = useModal(); + //注册table数据 + const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({ + tableProps:{ + title: '${tableVo.ftlDescription}', + api: list, + columns, + canResize:false, + useSearchForm: false, + actionColumn: { + width: 120, + fixed:'right' + }, + beforeFetch: (params) => { + return Object.assign(params, queryParam.value); + }, + }, + exportConfig: { + name:"${tableVo.ftlDescription}", + url: getExportUrl, + }, + importConfig: { + url: getImportUrl, + success: handleSuccess + }, + }) + + const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext + + /** + * 新增事件 + */ + function handleAdd() { + openModal(true, { + isUpdate: false, + showFooter: true, + }); + } + /** + * 编辑事件 + */ + function handleEdit(record: Recordable) { + openModal(true, { + record, + isUpdate: true, + showFooter: true, + }); + } + /** + * 详情 + */ + function handleDetail(record: Recordable) { + openModal(true, { + record, + isUpdate: true, + showFooter: false, + }); + } + /** + * 删除事件 + */ + async function handleDelete(record) { + await deleteOne({id: record.id}, handleSuccess); + } + /** + * 批量删除事件 + */ + async function batchHandleDelete() { + await batchDelete({ids: selectedRowKeys.value},handleSuccess); + } + /** + * 成功回调 + */ + function handleSuccess() { + (selectedRowKeys.value = []) && reload(); + } + /** + * 操作栏 + */ + function getTableAction(record){ + return [ + { + label: '编辑', + onClick: handleEdit.bind(null, record), + } + ] + } + /** + * 下拉操作栏 + */ + function getDropDownAction(record){ + return [ + { + label: '详情', + onClick: handleDetail.bind(null, record), + }, { + label: '删除', + popConfirm: { + title: '是否确认删除', + confirm: handleDelete.bind(null, record), + } + } + ] + } + <#if need_category> + /** + * form点击事件 + * @param value + */ + function handleFormChange(key, value) { + queryParam.value[key] = value; + } + /** + * 初始化字典配置 + */ + function initDictConfig(){ + <#list columns as po> + <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'> + <#if po.classType=='cat_tree' && need_category==true> + loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => { + if (res) { + let allDictDate = getAuthCache(DB_DICT_DATA_KEY); + if(!allDictDate['${po.dictField?default("")}']){ + Object.assign(allDictDate,{'${po.dictField?default("")}':res}) + } + setAuthCache(DB_DICT_DATA_KEY,allDictDate) + } + }) + </#if> + </#if> + </#list> + } + initDictConfig(); + </#if> + + /* ----------------------以下为原生查询需要添加的-------------------------- */ + const queryParam = ref<any>({}); + const toggleSearchStatus = ref<boolean>(false); + const labelCol = reactive({ + xs: { span: 24 }, + sm: { span: 7 }, + }); + const wrapperCol = reactive({ + xs: { span: 24 }, + sm: { span: 16 }, + }); + /** + * 重置 + */ + function searchReset() { + queryParam.value = {}; + selectedRowKeys.value = []; + //刷新数据 + reload(); + } + <#if need_popup> + /** + * popup组件值改变事件 + */ + function setFieldsValue(map) { + Object.keys(map).map((key) => { + queryParam.value[key] = map[key]; + }); + } + </#if> + + <#if need_pca> + /** + * 省市区点击事件 + * @param key + * @param value + */ + function handleAreaChange(key, value) { + queryParam.value[key] = value.join(','); + } + </#if> +</script> +<style lang="less" scoped> + .jeecg-basic-table-form-container { + .table-page-search-submitButtons { + display: block; + margin-bottom: 24px; + white-space: nowrap; + } + .query-group-cust{ + width: calc(50% - 15px); + min-width: 100px !important; + } + .query-group-split-cust{ + width: 30px; + display: inline-block; + text-align: center + } + } +</style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi new file mode 100644 index 0000000..74f56d1 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__api.tsi @@ -0,0 +1,82 @@ +import {defHttp} from '/@/utils/http/axios'; +import {Modal} from 'ant-design-vue'; + +enum Api { + list = '/${entityPackage}/${entityName?uncap_first}/list', + save='/${entityPackage}/${entityName?uncap_first}/add', + edit='/${entityPackage}/${entityName?uncap_first}/edit', + deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete', + deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch', + importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel', + exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls', + queryDataById = '/${entityPackage}/${entityName?uncap_first}/queryById', +<#list subTables as sub><#rt/> + ${sub.entityName?uncap_first}List = '/${entityPackage}/${entityName?uncap_first}/query${sub.entityName}ByMainId', +</#list> +} +/** + * 导出api + * @param params + */ +export const getExportUrl = Api.exportXls; + +/** + * 导入api + */ +export const getImportUrl = Api.importExcel; + +<#list subTables as sub><#rt/> +/** + * 查询子表数据 + * @param params + */ +export const query${sub.entityName}ListByMainId = (id) => defHttp.get({url: Api.${sub.entityName?uncap_first}List, params:{ id }}); +</#list> + +/** + * 列表接口 + * @param params + */ +export const list = (params) => + defHttp.get({url: Api.list, params}); + +/** + * 删除单个 + */ +export const deleteOne = (params,handleSuccess) => { + return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => { + handleSuccess(); + }); +} +/** + * 批量删除 + * @param params + */ +export const batchDelete = (params, handleSuccess) => { + Modal.confirm({ + title: '确认删除', + content: '是否删除选中数据', + okText: '确认', + cancelText: '取消', + onOk: () => { + return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => { + handleSuccess(); + }); + } + }); +} +/** + * 保存或者更新 + * @param params + */ +export const saveOrUpdate = (params, isUpdate) => { + let url = isUpdate ? Api.edit : Api.save; + return defHttp.post({url: url, params}); +} + +/** +* 根据id查询数据 +* @param params +*/ +export const queryDataById = (id) => defHttp.get({url: Api.queryDataById, params:{ id }}); + diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi new file mode 100644 index 0000000..243f984 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}__data.tsi @@ -0,0 +1,714 @@ +<#include "/common/utils.ftl"> +import {BasicColumn} from '/@/components/Table'; +import {FormSchema} from '/@/components/Table'; +import { rules} from '/@/utils/helper/validator'; +import { render } from '/@/utils/common/renderUtils'; +import {JVxeTypes,JVxeColumn} from '/@/components/jeecg/JVxeTable/types' +//列表数据 +export const columns: BasicColumn[] = [ + <#list columns as po> + <#if po.isShowList =='Y' && po.fieldName !='id'> + { + title: '${po.filedComment}', + align:"center", + <#if po.sort=='Y'> + sorter: true, + </#if> + <#if po.classType=='date'> + dataIndex: '${po.fieldName}', + customRender:({text}) =>{ + return !text?"":(text.length>10?text.substr(0,10):text) + }, + <#elseif po.fieldDbType=='Blob'> + dataIndex: '${po.fieldName}String' + <#elseif po.classType=='umeditor'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'htmlSlot' }, + <#elseif po.classType=='pca'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'pcaSlot' }, + <#elseif po.classType=='file'> + dataIndex: '${po.fieldName}', + slots: { customRender: 'fileSlot' }, + <#elseif po.classType=='image'> + dataIndex: '${po.fieldName}', + customRender:render.renderImage, + <#elseif po.classType=='switch'> + dataIndex: '${po.fieldName}', +<#assign switch_extend_arr=['Y','N']> +<#if po.dictField?default("")?contains("[")> +<#assign switch_extend_arr=po.dictField?eval> +</#if> +<#list switch_extend_arr as a> +<#if a_index == 0> +<#assign switch_extend_arr1=a> +<#else> +<#assign switch_extend_arr2=a> +</#if> +</#list> + customRender:({text}) => { + return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]) + }, + <#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'> + dataIndex: '${po.fieldName}_dictText' + <#elseif po.classType=='cat_tree'> + dataIndex: '${po.fieldName}', + <#if po.dictText?default("")?trim?length == 0> + customRender:({text}) => { + return render.renderCategoryTree(text,'${po.dictField?default("")}') + }, + <#else> + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') + </#if> + <#else> + dataIndex: '${po.fieldName}' + </#if> + }, + </#if> + </#list> +]; +//查询数据 +export const searchFormSchema: FormSchema[] = [ +<#-- 开始循环 --> +<#list columns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.isQuery=='Y'> +<#assign query_flag=true> + <#assign query_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign query_field_dictCode="${po.dictField}"> + </#if> +<#if po.queryMode=='single'> + { + label: "${po.filedComment}", + field: "${po.fieldName}", +<#if po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps:{ + dict:"${po.dictTable},${po.dictText},${po.dictField}" + }, +<#elseif po.classType=='sel_user'> + component: 'JSelectUserByDept', +<#elseif po.classType=='switch'> + component: 'JSwitch', + componentProps:{ + <#if po.dictField != 'is_open'> + options:"${po.dictField}" + </#if> + }, + <#elseif po.classType=='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType=='list_multi'> + component: 'JSelectMultiple', + componentProps:{ + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true + }, + <#elseif po.classType=='cat_tree'> + component: 'JCategorySelect', + componentProps:{ + pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题 + }, +<#elseif po.classType=='date'> + component: 'DatePicker', +<#elseif po.classType=='datetime'> + component: 'DatePicker', + componentProps: { + showTime:true + }, +<#elseif po.classType=='pca'> + component: 'JAreaLinkage', +<#elseif po.classType=='popup'> + <#include "/common/form/vue3popup.ftl"> +<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> +<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> + component: 'JDictSelectTag', + componentProps:{ + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}" + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}" + </#if> + }, +<#else> + component: 'Input', +</#if> + colProps: {span: 6}, + }, +<#else> + { + label: "${po.filedComment}", + field: "${po.fieldName}", +<#if po.classType=='date'> + component: 'RangePicker', +<#elseif po.classType=='datetime'> + component: 'RangePicker', + componentProps: { + showTime:true + }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', +<#else> + component: 'Input', //TODO 范围查询 +</#if> + colProps: {span: 6}, + }, +</#if> +</#if> +</#list> +<#-- 结束循环 --> +]; +//表单数据 +export const formSchema: FormSchema[] = [ +<#assign form_cat_tree = false> +<#assign form_cat_back = ""> +<#assign bpm_flag=false> +<#assign id_exists = false> +<#list columns as po><#rt/> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.fieldDbName == 'id'> + <#assign id_exists = true> +</#if> +<#if po.isShow =='Y'> +<#assign form_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictField}"> + </#if> + { + label: '${po.filedComment}', + field: ${autoStringSuffix(po)}, + <#if po.classType =='date'> + component: 'DatePicker', + <#elseif po.classType =='datetime'> + component: 'DatePicker', + componentProps: { + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' + }, + <#elseif po.classType =='time'> + component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, + <#elseif po.classType =='popup'> + <#include "/common/form/vue3popup.ftl"> + <#elseif po.classType =='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType =='switch'> + component: 'JSwitch', + componentProps:{ + <#if po.dictField != 'is_open'> + options:${po.dictField} + </#if> + }, + <#elseif po.classType =='pca'> + component: 'JAreaLinkage', + <#elseif po.classType =='markdown'> + component: 'JMarkdownEditor',//注意string转换问题 + <#elseif po.classType =='password'> + component: 'InputPassword', + <#elseif po.classType =='sel_user'> + component: 'JSelectUserByDept', + componentProps:{ + labelKey:'realname', + }, + <#elseif po.classType =='textarea'> + component: 'InputTextArea', + <#elseif po.classType=='list' || po.classType=='radio'> + component: 'JDictSelectTag', + componentProps:{ + dictCode:"${form_field_dictCode}" + }, + <#elseif po.classType=='list_multi' || po.classType=='checkbox'> + component: 'JSelectMultiple', + componentProps:{ + dictCode:"${form_field_dictCode}" + }, + <#elseif po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps:{ + dict:"${form_field_dictCode}" + }, +<#elseif po.classType=='cat_tree'> + <#assign form_cat_tree = true> + component: 'JCategorySelect', + componentProps:{ + pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题 + }, + <#if po.dictText?default("")?trim?length gt 1> + <#assign form_cat_back = "${po.dictText}"> + </#if> + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'InputNumber', + <#elseif po.classType=='file'> + component: 'JUpload', + componentProps:{ + <#if po.uploadnum??> + maxCount:${po.uploadnum} + </#if> + }, + <#elseif po.classType=='image'> + component: 'JImageUpload', + componentProps:{ + <#if po.uploadnum??> + fileMax:${po.uploadnum} + </#if> + }, + <#elseif po.classType=='umeditor'> + component: 'JEditor', + <#elseif po.classType == 'sel_tree'> + component: 'JTreeSelect', + componentProps:{ + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}", + <#elseif po.dictText?split(',')[1]??> + pidField:"${po.dictText?split(',')[1]}", + <#elseif po.dictText?split(',')[3]??> + hasChildField:"${po.dictText?split(',')[3]}", + </#if> + </#if> + pidValue:"${po.dictField}", + }, + <#else> + component: 'Input', + </#if> + <#include "/common/utils.ftl"> + <#if po.isShow == 'Y' && poHasCheck(po)> + dynamicRules: ({model,schema}) => { + <#if po.fieldName != 'id'> + <#assign fieldValidType = po.fieldValidType!''> + return [ + <#-- 非空校验 --> + <#if po.nullable == 'N' || fieldValidType == '*'> + { required: true, message: '请输入${po.filedComment}!'}, + <#elseif fieldValidType!=''> + { required: false}, + </#if> + <#-- 唯一校验 --> + <#if fieldValidType == 'only'> + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, + <#-- 6到16位数字 --> + <#elseif fieldValidType == 'n6-16'> + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, + <#-- 6到16位任意字符 --> + <#elseif fieldValidType == '*6-16'> + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, + <#-- 6到18位字符串 --> + <#elseif fieldValidType == 's6-18'> + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + <#-- 网址 --> + <#elseif fieldValidType == 'url'> + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, + <#-- 电子邮件 --> + <#elseif fieldValidType == 'e'> + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}, + <#-- 手机号码 --> + <#elseif fieldValidType == 'm'> + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, + <#-- 邮政编码 --> + <#elseif fieldValidType == 'p'> + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + <#-- 字母 --> + <#elseif fieldValidType == 's'> + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, + <#-- 数字 --> + <#elseif fieldValidType == 'n'> + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}, + <#-- 整数 --> + <#elseif fieldValidType == 'z'> + { pattern: /^-?\d+$/, message: '请输入整数!'}, + <#-- 金额 --> + <#elseif fieldValidType == 'money'> + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}, + <#-- 正则校验 --> + <#elseif fieldValidType != '' && fieldValidType != '*'> + { pattern: '${fieldValidType}', message: '不符合校验规则!'}, + <#-- 无校验 --> + <#else> + <#t> + </#if> + ]; + </#if> + }, + </#if> + <#if po.readonly=='Y'> + dynamicDisabled:true + </#if> + }, +</#if> +</#list> +<#if id_exists == false> + // TODO 主键隐藏字段,目前写死为ID + { + label: '', + field: 'id', + component: 'Input', + show: false + }, +</#if> +]; +//子表单数据 +<#list subTables as sub> +<#if sub.foreignRelationType =='1'> +export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ +<#assign form_cat_tree = false> +<#assign form_cat_back = ""> +<#assign bpm_flag=false> +<#assign sub_id_exists=false> +<#list sub.colums as po><#rt/> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> +</#if> +<#if po.fieldDbName=='id'> + <#assign sub_id_exists=true> +</#if> +<#if po.isShow =='Y'> +<#assign form_field_dictCode=""> + <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}"> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign form_field_dictCode="${po.dictField}"> + </#if> + { + label: '${po.filedComment}', + field: ${autoStringSuffix(po)}, + <#if po.classType =='date'> + component: 'DatePicker', + <#elseif po.classType =='datetime'> + component: 'DatePicker', + componentProps: { + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' + }, + <#elseif po.classType =='time'> + component: 'TimePicker', + componentProps: { + valueFormat: 'HH:mm:ss' + }, + <#elseif po.classType =='popup'> + <#include "/common/form/vue3popup.ftl"> + <#elseif po.classType =='sel_depart'> + component: 'JSelectDept', + <#elseif po.classType =='switch'> + component: 'JSwitch', + componentProps:{ + <#if po.dictField != 'is_open'> + options:${po.dictField} + </#if> + }, + <#elseif po.classType =='pca'> + component: 'JAreaLinkage', + <#elseif po.classType =='markdown'> + component: 'JMarkdownEditor',//注意string转换问题 + <#elseif po.classType =='password'> + component: 'InputPassword', + <#elseif po.classType =='sel_user'> + component: 'JSelectUserByDept', + componentProps:{ + labelKey:'realname', + }, + <#elseif po.classType =='textarea'> + component: 'InputTextArea', + <#elseif po.classType=='list' || po.classType=='radio'> + component: 'JDictSelectTag', + componentProps:{ + dictCode:"${form_field_dictCode}" + }, + <#elseif po.classType=='list_multi' || po.classType=='checkbox'> + component: 'JSelectMultiple', + componentProps:{ + dictCode:"${form_field_dictCode}" + } + <#elseif po.classType=='sel_search'> + component: 'JSearchSelect', + componentProps:{ + dict:"${form_field_dictCode}" + }, +<#elseif po.classType=='cat_tree'> + <#assign form_cat_tree = true> + component: 'JCategorySelect', + componentProps:{ + pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题 + }, + <#if po.dictText?default("")?trim?length gt 1> + <#assign form_cat_back = "${po.dictText}"> + </#if> + <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'InputNumber', + <#elseif po.classType=='file'> + component: 'JUpload', + componentProps:{ + <#if po.uploadnum??> + maxCount:${po.uploadnum} + </#if> + }, + <#elseif po.classType=='image'> + component: 'JImageUpload', + componentProps:{ + <#if po.uploadnum??> + fileMax:${po.uploadnum} + </#if> + }, + <#elseif po.classType=='umeditor'> + component: 'JEditor', + <#elseif po.classType == 'sel_tree'> + component: 'JTreeSelect', + componentProps:{ + <#if po.dictText??> + <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??> + dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}", + <#elseif po.dictText?split(',')[1]??> + pidField:"${po.dictText?split(',')[1]}", + <#elseif po.dictText?split(',')[3]??> + hasChildField:"${po.dictText?split(',')[3]}", + </#if> + </#if> + pidValue:"${po.dictField}", + }, + <#else> + component: 'Input', + </#if> + <#include "/common/utils.ftl"> + <#if po.isShow == 'Y' && poHasCheck(po)> + dynamicRules: ({model,schema}) => { + <#if po.fieldName != 'id'> + <#assign fieldValidType = po.fieldValidType!''> + return [ + <#-- 非空校验 --> + <#if po.nullable == 'N' || fieldValidType == '*'> + { required: true, message: '请输入${po.filedComment}!'}, + <#elseif fieldValidType!=''> + { required: false}, + </#if> + <#-- 唯一校验 --> + <#if fieldValidType == 'only'> + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, + <#-- 6到16位数字 --> + <#elseif fieldValidType == 'n6-16'> + { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, + <#-- 6到16位任意字符 --> + <#elseif fieldValidType == '*6-16'> + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, + <#-- 6到18位字符串 --> + <#elseif fieldValidType == 's6-18'> + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + <#-- 网址 --> + <#elseif fieldValidType == 'url'> + { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, + <#-- 电子邮件 --> + <#elseif fieldValidType == 'e'> + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}, + <#-- 手机号码 --> + <#elseif fieldValidType == 'm'> + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, + <#-- 邮政编码 --> + <#elseif fieldValidType == 'p'> + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + <#-- 字母 --> + <#elseif fieldValidType == 's'> + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, + <#-- 数字 --> + <#elseif fieldValidType == 'n'> + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}, + <#-- 整数 --> + <#elseif fieldValidType == 'z'> + { pattern: /^-?\d+$/, message: '请输入整数!'}, + <#-- 金额 --> + <#elseif fieldValidType == 'money'> + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}, + <#-- 正则校验 --> + <#elseif fieldValidType != '' && fieldValidType != '*'> + { pattern: '${fieldValidType}', message: '不符合校验规则!'}, + <#-- 无校验 --> + <#else> + <#t> + </#if> + ]; + </#if> + }, + </#if> + <#if po.readonly=='Y'> + dynamicDisabled:true + </#if> + }, +</#if> +</#list> +<#if sub_id_exists == false> + { + label: '', + field: 'id', + component: 'Input', + show: false + }, +</#if> +]; +</#if> +</#list> +//子表表格配置 +<#list subTables as sub> +<#if sub.foreignRelationType =='0'> +export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ +<#assign popupBackFields = ""> + +<#-- 循环子表的列 开始 --> +<#list sub.colums as col><#rt/> +<#if col.isShow =='Y'> +<#if col.filedComment !='外键' > + { + title: '${col.filedComment}', + key: '${autoStringSuffixForModel(col)}', +<#if col.classType =='date'> + type: JVxeTypes.date, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='datetime'> + type: JVxeTypes.datetime, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='time'> + type: JVxeTypes.time, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='textarea'> + type: JVxeTypes.textarea, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#-- update-begin-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> +<#-- elseif "int,decimal,double,"?contains(col.classType) --> +<#elseif col.fieldDbType=='int' || col.fieldDbType=='double' || col.fieldDbType=='BigDecimal'> +<#-- update-end-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> + type: JVxeTypes.inputNumber, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='list' || col.classType =='radio'> + type: JVxeTypes.select, + options:[], + <#if col.dictTable?default("")?trim?length gt 1> + dictCode:"${col.dictTable},${col.dictText},${col.dictField}", + <#else> + dictCode:"${col.dictField}", + </#if> + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='list_multi' || col.classType =='checkbox'> + type: JVxeTypes.selectMultiple, + options:[], + <#if col.dictTable?default("")?trim?length gt 1> + dictCode:"${col.dictTable},${col.dictText},${col.dictField}", + <#else> + dictCode:"${col.dictField}", + </#if> + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='sel_search'> + type: JVxeTypes.selectSearch, + <#if col.dictTable?default("")?trim?length gt 1> + dictCode:"${col.dictTable},${col.dictText},${col.dictField}", + <#else> + dictCode:"${col.dictField}", + </#if> + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='sel_depart'> + type: JVxeTypes.departSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='sel_user'> + type: JVxeTypes.userSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='image'> + type: JVxeTypes.image, + token:true, + responseName:"message", + <#if col.readonly=='Y'> + disabled:true, + </#if> + <#if col.uploadnum??> + number: ${col.uploadnum}, + </#if> +<#elseif col.classType =='file'> + type: JVxeTypes.file, + token:true, + responseName:"message", + <#if col.readonly=='Y'> + disabled:true, + </#if> + <#if col.uploadnum??> + number: ${col.uploadnum}, + </#if> +<#elseif col.classType =='switch'> + type: JVxeTypes.checkbox, + <#if col.dictField == 'is_open'> + customValue: ['Y', 'N'], + <#else> + customValue: ${col.dictField}, + </#if> + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='popup'> +<#if popupBackFields?length gt 0> + <#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}"> +<#else> + <#assign popupBackFields = "${col.dictText}"> +</#if> + <#include "/common/form/vue3Jvxepopup.ftl"> +<#else> + type: JVxeTypes.input, + <#if col.readonly=='Y'> + disabled:true, + </#if> +</#if> +<#if col.classType =='list_multi' || col.classType =='checkbox'> + width:"250px", +<#else> + width:"200px", +</#if> +<#if col.classType =='file'> + placeholder: '请选择文件', +<#else> + placeholder: '请输入${'$'}{title}', +</#if> +<#if col.defaultVal??> +<#if col.fieldDbType=="BigDecimal" || col.fieldDbType=="double" || col.fieldDbType=="int"> + defaultValue:${col.defaultVal}, + <#else> + defaultValue:"${col.defaultVal}", +</#if> +<#else> + defaultValue:'', +</#if> +<#-- 子表的校验 --> + <#include "/common/validatorRulesTemplate/sub-vue3.ftl"> + }, +</#if> +</#if> +</#list> +<#-- 循环子表的列 结束 --> + ] +</#if> +</#list> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei new file mode 100644 index 0000000..e3e4cf8 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Form.vuei @@ -0,0 +1,264 @@ +<#include "/common/utils.ftl"> +<#assign need_category = false> +<#assign bpm_flag=false> +<#assign need_pca = false> +<#assign need_search = false> +<#assign need_dept_user = false> +<#assign need_switch = false> +<#assign need_dept = false> +<#assign need_multi = false> +<#assign need_popup = false> +<#assign need_select_tag = false> +<#assign need_select_tree = false> +<#assign need_time = false> +<#assign need_markdown = false> +<#assign need_upload = false> +<#assign need_image_upload = false> +<#assign need_editor = false> +<#assign need_checkbox = false> +<#assign form_span = 24> +<#if tableVo.fieldRowNum==2> + <#assign form_span = 12> +<#elseif tableVo.fieldRowNum==3> + <#assign form_span = 8> +<#elseif tableVo.fieldRowNum==4> + <#assign form_span = 6> +</#if> +<#assign hasOne2manyTable = false> +<#assign subTabActiveKey = ''> +<#assign subMainFieldMap={}> +<#assign subTableColumnsKey=[]> +<#assign hasOnlyValidate = false> +<template> + <a-spin :spinning="loading"> + <a-form v-bind="formItemLayout"> + <a-row> + <#list columns as po> + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + <#assign hasOnlyValidate = true> + </#if> + <#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + </#if> +<#include "/common/form/native/vue3NativeForm.ftl"> + </#list> + </a-row> + </a-form> + + <!-- 子表单区域 --> + <a-tabs v-model:activeKey="activeKey"> +<#list subTables as sub><#rt/> + <a-tab-pane tab="${sub.ftlDescription}" key="${sub.entityName?uncap_first}" :forceRender="true"> + <#if sub.foreignRelationType =='1'> + <${Format.humpToShortbar(sub.entityName)}-form ref="${sub.entityName?uncap_first}FormRef" :disabled="formDisabled"></${Format.humpToShortbar(sub.entityName)}-form> + <#else> + <j-vxe-table + :keep-source="true" + ref="${sub.entityName?uncap_first}TableRef" + :loading="${sub.entityName?uncap_first}Table.loading" + :columns="${sub.entityName?uncap_first}Table.columns" + :dataSource="${sub.entityName?uncap_first}Table.dataSource" + :maxHeight="300" + :disabled="formDisabled" + :rowNumber="true" + :rowSelection="true" + :toolbar="true"/> + </#if> + </a-tab-pane> +</#list> + </a-tabs> + </a-spin> +</template> + +<script lang="ts"> + import { defineComponent, ref, reactive, computed, toRaw } from 'vue'; + import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods'; + import { <#list subTables as sub><#if sub.foreignRelationType =='0'>query${sub.entityName}ListByMainId, </#if></#list>queryDataById, saveOrUpdate } from '../${entityName}.api'; + <#list subTables as sub> + <#if sub.foreignRelationType =='1'> + import ${sub.entityName}Form from './${sub.entityName}Form.vue' + <#else> + <#assign hasOne2manyTable = true> + <#assign subTableColumnsKey += ['${sub.entityName?uncap_first}Columns']> + </#if> + <#if sub?? && (sub.foreignMainKeys)??> + <#list sub.foreignMainKeys as key> + <#assign subMainFieldMap += {"${sub.entityName}": "${dashedToCamel(key)}"}> + </#list> + </#if> + </#list> + <#if hasOne2manyTable == true> + import { JVxeTable } from '/@/components/jeecg/JVxeTable'; + import {<#list subTableColumnsKey as columnsKey><#if columnsKey_index gt 0>, </#if>${columnsKey}</#list>} from '../${entityName}.data'; + </#if> + <#include "/common/form/native/vue3NativeImport.ftl"> + <#if hasOnlyValidate == true> + import { duplicateValidate } from '/@/utils/helper/validator' + </#if> + import { Form } from 'ant-design-vue'; + const useForm = Form.useForm; + + export default defineComponent({ + name: "${entityName}Form", + components:{ + <#include "/common/form/native/vue3NativeComponents.ftl"> + <#if hasOne2manyTable == true> + JVxeTable, + </#if> +<#list subTables as sub> + <#if sub.foreignRelationType =='1'> + ${sub.entityName}Form, + </#if> +</#list> + }, + props:{ + disabled:{ + type: Boolean, + default: false + } + }, + emits:['success'], + setup(props, {emit}) { + const loading = ref(false); + <#list subTables as sub> + <#if sub_index == 0> + <#assign subTabActiveKey = '${sub.entityName?uncap_first}'> + </#if> + <#if sub.foreignRelationType =='1'> + const ${sub.entityName?uncap_first}FormRef = ref(); + <#else> + const ${sub.entityName?uncap_first}TableRef = ref(); + const ${sub.entityName?uncap_first}Table = reactive<Record<string, any>>({ + loading: false, + columns: ${sub.entityName?uncap_first}Columns, + dataSource: [] + }); + </#if> + </#list> + const activeKey = ref('${subTabActiveKey}'); + const formData = reactive<Record<string, any>>({ + <#list columns as po> + <#if po.isShow == 'Y'> + ${po.fieldName}: '', + </#if> + </#list> + }); + + //表单验证 + const validatorRules = reactive({ + <#list columns as po> + <#if po.isShow == 'Y' && poHasCheck(po)> + ${po.fieldName}: [<#include "/common/validatorRulesTemplate/native/vue3CoreNative.ftl">], + </#if> + </#list> + }); + const {resetFields, validate, validateInfos} = useForm(formData, validatorRules, {immediate: true}); + const dbData = {}; + const formItemLayout = { + labelCol: {xs: {span: 24}, sm: {span: 5}}, + wrapperCol: {xs: {span: 24}, sm: {span: 16}}, + }; + + const formDisabled = computed(() => { + return props.disabled; + }); + + function add() { + resetFields(); + <#list subTables as sub> + <#if sub.foreignRelationType =='1'> + ${sub.entityName?uncap_first}FormRef.value.initFormData(); + <#else> + ${sub.entityName?uncap_first}Table.dataSource = []; + </#if> + </#list> + } + + async function edit(row) { + //主表数据 + await queryMainData(row.id); + //子表数据 + <#list subTables as sub> + <#if sub.foreignRelationType =='1'> + await ${sub.entityName?uncap_first}FormRef.value.initFormData(row['${subMainFieldMap[sub.entityName]}']); + <#else> + const ${sub.entityName?uncap_first}DataList = await query${sub.entityName}ListByMainId(row['${subMainFieldMap[sub.entityName]}']); + ${sub.entityName?uncap_first}Table.dataSource = [...${sub.entityName?uncap_first}DataList]; + </#if> + </#list> + } + + async function queryMainData(id) { + const row = await queryDataById(id); + Object.keys(row).map(k => { + formData[k] = row[k]; + }); + } + + const {getSubFormAndTableData, transformData} = useValidateAntFormAndTable(activeKey, { + <#list subTables as sub> + <#if sub.foreignRelationType =='1'> + '${sub.entityName?uncap_first}': ${sub.entityName?uncap_first}FormRef, + <#else> + '${sub.entityName?uncap_first}': ${sub.entityName?uncap_first}TableRef, + </#if> + </#list> + }); + + async function getFormData() { + await validate(); + return transformData(toRaw(formData)) + } + + async function submitForm() { + const mainData = await getFormData(); + const subData = await getSubFormAndTableData(); + const values = Object.assign({}, dbData, mainData, subData); + console.log('表单提交数据', values) + const isUpdate = values.id ? true : false + await saveOrUpdate(values, isUpdate); + //关闭弹窗 + emit('success'); + } + + function setFieldsValue(values) { + if(values){ + Object.keys(values).map(k=>{ + formData[k] = values[k]; + }); + } + } + + <#list columns as po> + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + async function ${po.fieldName}Duplicatevalidate(_r, value) { + return duplicateValidate('${tableName}', '${po.fieldDbName}', value, formData.id || '') + } + </#if> + </#list> + + return { + <#list subTables as sub> + <#if sub.foreignRelationType =='1'> + ${sub.entityName?uncap_first}FormRef, + <#else> + ${sub.entityName?uncap_first}TableRef, + ${sub.entityName?uncap_first}Table, + </#if> + </#list> + validatorRules, + validateInfos, + activeKey, + loading, + formData, + setFieldsValue, + formItemLayout, + formDisabled, + getFormData, + submitForm, + add, + edit + } + } + }); +</script> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei new file mode 100644 index 0000000..24366e8 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/${entityName}Modal.vuei @@ -0,0 +1,69 @@ +<#include "/common/utils.ftl"> +<template> + <BasicModal v-bind="$attrs" @register="registerModal" :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> + <${Format.humpToShortbar(entityName)}-form ref="formComponent" :disabled="formDisabled" @success="submitSuccess"></${Format.humpToShortbar(entityName)}-form> + </BasicModal> +</template> + +<script lang="ts"> + import { ref, unref } from 'vue'; + import { BasicModal, useModalInner } from '/@/components/Modal'; + import ${entityName}Form from './${entityName}Form.vue'; + + export default { + name: "TestCgMainVxeModal", + components:{ + BasicModal, + ${entityName}Form + }, + emits:['register','success'], + setup(_p, {emit}){ + const formComponent = ref() + const isUpdate = ref(true); + const formDisabled = ref(false); + const title = ref('') + + //表单赋值 + const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { + setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter}); + isUpdate.value = !!data?.isUpdate; + title.value = data?.isUpdate?'编辑':'新增' + formDisabled.value = !data?.showFooter; + if (unref(isUpdate)) { + console.log('data', data) + formComponent.value.edit(data.record) + }else{ + formComponent.value.add() + } + }); + + function handleSubmit() { + formComponent.value.submitForm(); + } + + function submitSuccess(){ + emit('success'); + closeModal(); + } + + return { + registerModal, + title, + formComponent, + formDisabled, + handleSubmit, + submitSuccess + } + } + } +</script> +<style lang="less" scoped> + /** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + + :deep(.ant-calendar-picker){ + width: 100% + } +</style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/[1-n]Form.vuei new file mode 100644 index 0000000..303fdbe --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue3Native/components/[1-n]Form.vuei @@ -0,0 +1,149 @@ +<#include "/common/utils.ftl"> +<#list subTables as sub> +<#if sub.foreignRelationType=='1'> +#segment#${sub.entityName}Form.vue +<#include "/common/utils.ftl"> +<#assign need_category = false> +<#assign bpm_flag=false> +<#assign need_pca = false> +<#assign need_search = false> +<#assign need_dept_user = false> +<#assign need_switch = false> +<#assign need_dept = false> +<#assign need_multi = false> +<#assign need_popup = false> +<#assign need_select_tag = false> +<#assign need_select_tree = false> +<#assign need_time = false> +<#assign need_markdown = false> +<#assign need_upload = false> +<#assign need_image_upload = false> +<#assign need_editor = false> +<#assign need_checkbox = false> +<#assign form_span = 24> +<#if tableVo.fieldRowNum==2> + <#assign form_span = 12> +<#elseif tableVo.fieldRowNum==3> + <#assign form_span = 8> +<#elseif tableVo.fieldRowNum==4> + <#assign form_span = 6> +</#if> + <#assign hasOnlyValidate = false> +<template> + <a-spin :spinning="loading"> + <a-form v-bind="formItemLayout"> + <a-row> + <#list sub.colums as po> + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + <#assign hasOnlyValidate = true> + </#if> + <#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + </#if> + <#include "/common/form/native/vue3NativeForm.ftl"> + </#list> + </a-row> + </a-form> + </a-spin> +</template> + +<script lang="ts"> + import { defineComponent, ref, reactive, toRaw } from 'vue'; + import { query${sub.entityName}ListByMainId } from '../${entityName}.api'; +<#include "/common/form/native/vue3NativeImport.ftl"> +<#if hasOnlyValidate == true> + import { duplicateValidate } from '/@/utils/helper/validator' +</#if> + import { useMessage } from '/@/hooks/web/useMessage'; + import { Form } from 'ant-design-vue'; + const useForm = Form.useForm; + + export default defineComponent({ + name: '${sub.entityName}Form', + components:{ + <#include "/common/form/native/vue3NativeComponents.ftl"> + }, + props:{ + disabled:{ + type: Boolean, + default: false + } + }, + setup(){ + const { createMessage } = useMessage(); + const isForm = true; + const loading = ref(false); + const formData = reactive<Record<string, any>>({ + <#list sub.colums as po> + <#if po.isShow == 'Y'> + ${po.fieldName}: '', + </#if> + </#list> + }); + //表单验证 + const validatorRules = reactive({ + <#list sub.colums as po> + <#if po.isShow == 'Y' && poHasCheck(po)> + ${po.fieldName}: [<#include "/common/validatorRulesTemplate/native/vue3CoreNative.ftl">], + </#if> + </#list> + }) + const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, {immediate: true}); + const formItemLayout = { + labelCol: { xs: { span: 24 }, sm: { span: 5 } }, + wrapperCol: { xs: { span: 24 }, sm: { span: 16 } }, + }; + + async function initFormData(mainId) { + resetFields(); + if(mainId){ + let list = await query${sub.entityName}ListByMainId(mainId); + if(list && list.length>0){ + let temp = list[0]; + Object.keys(temp).map(k=>{ + formData[k] = temp[k]; + }) + } + } + } + + async function getFormData() { + await validate(); + let subFormData = toRaw(formData); + if(Object.keys(subFormData).length>0){ + return subFormData + } + return false; + } + + function setFieldsValue(values) { + if(values){ + Object.keys(values).map(k=>{ + formData[k] = values[k]; + }); + } + } + + <#list sub.colums as po> + <#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'> + async function ${po.fieldName}Duplicatevalidate(_r, value) { + return duplicateValidate('${sub.tableName}', '${po.fieldDbName}', value, formData.id || '') + } + </#if> + </#list> + + return { + loading, + formData, + formItemLayout, + initFormData, + getFormData, + setFieldsValue, + isForm, + validateInfos + } + } + }); +</script> +</#if> +</#list> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai index 4877656..b2581f9 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -196,17 +196,14 @@ public class ${entityName}Controller { QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - //Step.2 获取导出数据 - List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); - // 过滤选中数据 - String selections = request.getParameter("selections"); - List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); - if(oConvertUtils.isEmpty(selections)) { - ${entityName?uncap_first}List = queryList; - }else { - List<String> selectionList = Arrays.asList(selections.split(",")); - ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); - } + //配置选中数据查询条件 + String selections = request.getParameter("selections"); + if(oConvertUtils.isNotEmpty(selections)) { + List<String> selectionList = Arrays.asList(selections.split(",")); + queryWrapper.in("id",selectionList); + } + //Step.2 获取导出数据 + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper); // Step.3 组装pageList List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai index c861c4a..4d1b425 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> package ${bussiPackage}.${entityPackage}.entity; import java.io.Serializable; @@ -31,9 +32,9 @@ public class ${entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai index b6aabe8..93ddf95 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as subTab> #segment#${subTab.entityName}.java package ${bussiPackage}.${entityPackage}.entity; @@ -32,9 +33,9 @@ public class ${subTab.entityName} implements Serializable { <#-- 生成字典Code --> <#assign list_field_dictCode=""> <#if po.classType='sel_user'> - <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "${camelToDashed(po.extendParams.text?default(\"realname\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"username\")?trim)}"'> <#elseif po.classType='sel_depart'> - <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "${camelToDashed(po.extendParams.text?default(\"depart_name\")?trim)}", dicCode = "${camelToDashed(po.extendParams.store?default(\"id\")?trim)}"'> <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> <#if po.dictTable?default("")?trim?length gt 1> <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei index c503847..5e82b9e 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -39,7 +39,7 @@ @input="popupCallback" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if>/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch> <#elseif po.classType =='pca'> @@ -49,7 +49,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei index ca111ff..ff5e255 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -44,7 +44,7 @@ :multi="${po.extendParams.popupMulti?c}" @input="popupCallback"/> <#elseif po.classType =='sel_depart'> - <j-select-depart v-model="model.${po.fieldName}" multi/> + <j-select-depart v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if> /> <#elseif po.classType =='switch'> <j-switch v-model="model.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if>></j-switch> <#elseif po.classType =='pca'> @@ -54,7 +54,7 @@ <#elseif po.classType =='password'> <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}"/> <#elseif po.classType =='sel_user'> - <j-select-user-by-dep v-model="model.${po.fieldName}"/> + <j-select-user-by-dep v-model="model.${po.fieldName}" :multi="${po.extendParams.multi?default('true')}"<#if po.extendParams.store?default("")?trim?length gt 0> store="${po.extendParams.store}"</#if><#if po.extendParams.text?default("")?trim?length gt 0> text="${po.extendParams.text}"</#if> <#if po.readonly=='Y'>disabled</#if>/> <#elseif po.classType =='textarea'> <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}"/> <#elseif po.classType=='list' || po.classType=='radio'> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei index fd577a1..6ba0f5b 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}List.vuei @@ -46,6 +46,10 @@ <template #htmlSlot="{text}"> <div v-html="text"></div> </template> + <!--省市区字段回显插槽--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> <template #fileSlot="{text}"> <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span> <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button> @@ -64,6 +68,10 @@ import ${entityName}Modal from './components/${entityName}Modal.vue' import {columns, searchFormSchema} from './${entityName}.data'; import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName}.api'; + import {downloadFile} from '/@/utils/common/renderUtils'; +<#if list_need_pca> + import { getAreaTextByCode } from '/@/components/Form/src/utils/Area'; +</#if> <#if list_need_category> import { loadCategoryData } from '/@/api/common/api' import { getAuthCache, setAuthCache } from '/@/utils/auth'; @@ -84,6 +92,17 @@ schemas: searchFormSchema, autoSubmitOnEnter:true, showAdvancedButton:true, + fieldMapToNumber: [ + <#list columns as po> + <#if po.isQuery=='Y'> + <#if po.queryMode!='single'> + <#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + ['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']], + </#if> + </#if> + </#if> + </#list> + ], fieldMapToTime: [ <#list columns as po> <#if po.isQuery=='Y'> @@ -98,9 +117,10 @@ </#list> ], }, - actionColumn: { + actionColumn: { width: 120, - }, + fixed:'right' + }, }, exportConfig: { name:"${tableVo.ftlDescription}", diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index 6d77bc2..09e94e9 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> import {BasicColumn} from '/@/components/Table'; import {FormSchema} from '/@/components/Table'; import { rules} from '/@/utils/helper/validator'; @@ -25,7 +26,7 @@ export const columns: BasicColumn[] = [ slots: { customRender: 'htmlSlot' }, <#elseif po.classType=='pca'> dataIndex: '${po.fieldName}', - slots: { customRender: 'pcaSlot' },//TODO 未翻译 + slots: { customRender: 'pcaSlot' }, <#elseif po.classType=='file'> dataIndex: '${po.fieldName}', slots: { customRender: 'fileSlot' }, @@ -57,7 +58,7 @@ export const columns: BasicColumn[] = [ return render.renderCategoryTree(text,'${po.dictField?default("")}') }, <#else> - customRender: (text, record) => (text ? record['${po.dictText}'] : '') + customRender: ({text, record}) => (text ? record['${po.dictText}'] : '') </#if> <#else> dataIndex: '${po.fieldName}' @@ -95,16 +96,22 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='switch'> component: 'JSwitch', componentProps:{ + query:true, <#if po.dictField != 'is_open'> - options:"${po.dictField}" + options:${po.dictField} </#if> }, <#elseif po.classType=='sel_depart'> component: 'JSelectDept', <#elseif po.classType=='list_multi'> - component: 'JMultiSelectTag',//暂无该组件 + component: 'JSelectMultiple', componentProps:{ - dictCode:"query_field_dictCode?default("")" + <#if po.dictTable?default("")?trim?length gt 1> + dictCode:"${po.dictTable},${po.dictText},${po.dictField}", + <#elseif po.dictField?default("")?trim?length gt 1> + dictCode:"${po.dictField}", + </#if> + triggerChange: true }, <#elseif po.classType=='cat_tree'> component: 'JCategorySelect', @@ -121,16 +128,7 @@ export const searchFormSchema: FormSchema[] = [ <#elseif po.classType=='pca'> component: 'JAreaLinkage', <#elseif po.classType=='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:"${po.dictField}", - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'> <#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- --> component: 'JDictSelectTag', @@ -157,6 +155,8 @@ export const searchFormSchema: FormSchema[] = [ componentProps: { showTime:true }, +<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'> + component: 'JRangeNumber', <#else> component: 'Input', //TODO 范围查询 </#if> @@ -189,27 +189,19 @@ export const formSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -231,14 +223,14 @@ export const formSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -273,7 +265,7 @@ export const formSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -305,16 +297,16 @@ export const formSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -373,10 +365,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ <#assign form_cat_tree = false> <#assign form_cat_back = ""> <#assign bpm_flag=false> +<#assign sub_id_exists = false> <#list sub.colums as po><#rt/> <#if po.fieldDbName=='bpm_status'> <#assign bpm_flag=true> </#if> +<#if po.fieldDbName == 'id'> + <#assign sub_id_exists = true> +</#if> <#if po.isShow =='Y'> <#assign form_field_dictCode=""> <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1> @@ -386,27 +382,19 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> { label: '${po.filedComment}', - field: '${po.fieldName}', + field: ${autoStringSuffix(po)}, <#if po.classType =='date'> component: 'DatePicker', - <#elseif po.fieldType =='datetime'> + <#elseif po.classType =='datetime'> component: 'DatePicker', componentProps: { - showTime:true + showTime:true, + valueFormat: 'YYYY-MM-DD HH:mm:ss' }, - <#elseif po.fieldType =='time'> + <#elseif po.classType =='time'> component: 'TimePicker', <#elseif po.classType =='popup'> - component: 'JPopup', - componentProps: ({ formActionType }) => { - const {setFieldsValue} = formActionType; - return{ - setFieldsValue:setFieldsValue, - code:"${po.dictTable}", - fieldConfig:${po.dictField}, - multi:${po.extendParams.popupMulti?c}, - } - }, + <#include "/common/form/vue3popup.ftl"> <#elseif po.classType =='sel_depart'> component: 'JSelectDept', <#elseif po.classType =='switch'> @@ -428,14 +416,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ labelKey:'realname', }, <#elseif po.classType =='textarea'> - component: 'InputTextArea',//TODO 注意string转换问题 + component: 'InputTextArea', <#elseif po.classType=='list' || po.classType=='radio'> component: 'JDictSelectTag', componentProps:{ dictCode:"${form_field_dictCode}" }, <#elseif po.classType=='list_multi' || po.classType=='checkbox'> - component: 'JMultiSelectTag',//TODO 暂无该组件 + component: 'JSelectMultiple', componentProps:{ dictCode:"${form_field_dictCode}" }, @@ -470,7 +458,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> }, <#elseif po.classType=='umeditor'> - component: 'JCodeEditor', //TODO String后缀暂未添加 + component: 'JEditor', <#elseif po.classType == 'sel_tree'> component: 'JTreeSelect', componentProps:{ @@ -502,16 +490,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ </#if> <#-- 唯一校验 --> <#if fieldValidType == 'only'> - {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]}, + {...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]}, <#-- 6到16位数字 --> <#elseif fieldValidType == 'n6-16'> { pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}, <#-- 6到16位任意字符 --> <#elseif fieldValidType == '*6-16'> { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, - <#-- 6到18位字符串 --> + <#-- 6到18位字母 --> <#elseif fieldValidType == 's6-18'> - { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + { pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'}, <#-- 网址 --> <#elseif fieldValidType == 'url'> { pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}, @@ -553,6 +541,14 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ }, </#if> </#list> +<#if sub_id_exists == false> + { + label: '', + field: 'id', + component: 'Input', + show: false + }, +</#if> ]; </#if> </#list> @@ -579,12 +575,20 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#if col.readonly=='Y'> disabled:true, </#if> +<#elseif col.classType =='time'> + type: JVxeTypes.time, + <#if col.readonly=='Y'> + disabled:true, + </#if> <#elseif col.classType =='textarea'> type: JVxeTypes.textarea, <#if col.readonly=='Y'> disabled:true, </#if> -<#elseif "int,decimal,double,"?contains(col.classType)> +<#-- update-begin-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> +<#-- elseif "int,decimal,double,"?contains(col.classType) --> +<#elseif col.fieldDbType=='int' || col.fieldDbType=='double' || col.fieldDbType=='BigDecimal'> +<#-- update-end-author:taoyan date:20220523 for: VUEN-1084 【vue3】online表单测试发现的新问题 20、一对多列字段类型生成的不对,数字或者金额类型 --> type: JVxeTypes.inputNumber, <#if col.readonly=='Y'> disabled:true, @@ -621,6 +625,16 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#if col.readonly=='Y'> disabled:true, </#if> +<#elseif col.classType =='sel_depart'> + type: JVxeTypes.departSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> +<#elseif col.classType =='sel_user'> + type: JVxeTypes.userSelect, + <#if col.readonly=='Y'> + disabled:true, + </#if> <#elseif col.classType =='image'> type: JVxeTypes.image, token:true, @@ -644,9 +658,9 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#elseif col.classType =='switch'> type: JVxeTypes.checkbox, <#if col.dictField == 'is_open'> - customValue: ['Y', 'N'], + customValue: ['Y', 'N'], <#else> - customValue: ${col.dictField}, + customValue: ${col.dictField}, </#if> <#if col.readonly=='Y'> disabled:true, @@ -657,14 +671,7 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ <#else> <#assign popupBackFields = "${col.dictText}"> </#if> - type: JVxeTypes.popup, - popupCode:"${col.dictTable}", - field:"${col.dictField}", - orgFields:"${col.dictField}", - destFields:"${Format.underlineToHump(col.dictText)}", - <#if col.readonly=='Y'> - disabled:true, - </#if> + <#include "/common/form/vue3Jvxepopup.ftl"> <#else> type: JVxeTypes.input, <#if col.readonly=='Y'> @@ -691,18 +698,7 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ defaultValue:'', </#if> <#-- 子表的校验 --> -<#assign subFieldValidType = col.fieldValidType!''> -<#-- 非空校验 --> -<#if col.nullable == 'N' || subFieldValidType == '*'> - validateRules: [{ required: true, message: '${'$'}{title}不能为空' }], -<#-- 其他情况下,只要有值就被认为是正则校验 --> -<#elseif subFieldValidType?length gt 0> -<#assign subMessage = '格式不正确'> -<#if subFieldValidType == 'only' > - <#assign subMessage = '不能重复'> -</#if> - validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }], -</#if> + <#include "/common/validatorRulesTemplate/sub-vue3.ftl"> }, </#if> </#if> diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql new file mode 100644 index 0000000..5396d5d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}_menu_insert.sql @@ -0,0 +1 @@ +<#include "/common/sql/menu_insert.ftl"> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei index aa5fe59..eade8bb 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/${entityName}Modal.vuei @@ -1,21 +1,22 @@ +<#include "/common/utils.ftl"> <template> - <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicModal ref="modalRef" destroyOnClose wrapClassName="j-cgform-tab-modal" v-bind="$attrs" @register="registerModal" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit"> <!-- 子表单区域 --> <a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs"> <!--主表区域 --> - <a-tab-pane tab="${tableVo.ftlDescription}" :key="refKeys[0]" :forceRender="true"> + <a-tab-pane tab="${tableVo.ftlDescription}" :key="refKeys[0]" :forceRender="true" :style="tabsStyle"> <BasicForm @register="registerForm" ref="formRef"/> </a-tab-pane> <!--子表单区域 --> <#list subTables as sub><#rt/> <#assign refKey = sub.entityName?uncap_first/> <#if sub.foreignRelationType =='1'> - <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true"> - <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form"></${sub.entityName}Form> + <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true" :style="tabsStyle"> + <${sub.entityName}Form ref="${sub.entityName?uncap_first}Form" :disabled="formDisabled"></${sub.entityName}Form> </a-tab-pane> <#else> - <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true"> + <a-tab-pane tab="${sub.ftlDescription}" key="${refKey}" :forceRender="true" :style="tabsStyle"> <JVxeTable keep-source resizable @@ -23,7 +24,8 @@ :loading="${sub.entityName?uncap_first}Table.loading" :columns="${sub.entityName?uncap_first}Table.columns" :dataSource="${sub.entityName?uncap_first}Table.dataSource" - :maxHeight="300" + :height="340" + :disabled="formDisabled" :rowNumber="true" :rowSelection="true" :toolbar="true" @@ -52,6 +54,8 @@ // Emits声明 const emit = defineEmits(['register','success']); const isUpdate = ref(true); + const formDisabled = ref(false); + const modalRef = ref(); const refKeys = ref(['${tableVo.entityName?uncap_first}',<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]); <#assign hasOne2Many = false> <#assign hasOne2One = false> @@ -81,6 +85,7 @@ labelWidth: 150, schemas: formSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); //表单赋值 const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { @@ -88,6 +93,7 @@ await reset(); setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter}); isUpdate.value = !!data?.isUpdate; + formDisabled.value = !data?.showFooter; if (unref(isUpdate)) { //表单赋值 await setFieldsValue({ @@ -109,9 +115,21 @@ }); //方法配置 const [handleChangeTabs,handleSubmit,requestSubTableData,formRef] = useJvxeMethod(requestAddOrEdit,classifyIntoFormData,tableRefs,activeKey,refKeys<#if hasOne2One==true>,validateSubForm</#if>); - - //设置标题 - const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑')); + // 弹窗tabs滚动区域的高度 + const tabsStyle = computed(() => { + let height: Nullable<string> = null + let minHeight = '100px' + let maxHeight: Nullable<string> = '500px' + // 弹窗wrapper + let modalWrapperRef = modalRef.value?.modalWrapperRef + if (modalWrapperRef) { + if (modalWrapperRef.fullScreen) { + height = 'calc(' + modalWrapperRef.spinStyle.height + ' - 50px)'; + maxHeight = null + } + } + return {height, minHeight, maxHeight} + }) async function reset(){ await resetFields(); @@ -180,5 +198,38 @@ </script> <style lang="less" scoped> +/** 时间和数字输入框样式 */ + :deep(.ant-input-number){ + width: 100% + } + + :deep(.ant-calendar-picker){ + width: 100% + } +</style> + +<style lang="less"> +// Online表单Tab风格专属样式 +.j-cgform-tab-modal { + .ant-modal-header { + padding-top: 8px; + padding-bottom: 8px; + border-bottom: none !important; + } + + .ant-modal .ant-modal-body > .scrollbar, + .ant-tabs-nav .ant-tabs-tab { + padding-top: 0; + } + + .ant-tabs-top-bar { + width: calc(100% - 55px); + position: relative; + left: -14px; + } + .ant-tabs .ant-tabs-top-content > .ant-tabs-tabpane { + overflow: hidden auto; + } +} </style> \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei index 6af0c52..9969aaf 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue3/components/[1-n]Form.vuei @@ -1,3 +1,4 @@ +<#include "/common/utils.ftl"> <#list subTables as sub> <#if sub.foreignRelationType=='1'> #segment#${sub.entityName}Form.vue @@ -15,11 +16,18 @@ name:"${sub.entityName}Form", components: {BasicForm}, emits:['register'], - setup(_,{emit}) { - const [registerForm, {resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({ + props:{ + disabled: { + type: Boolean, + default: false + } + }, + setup(props,{emit}) { + const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({ labelWidth: 150, schemas: ${sub.entityName?uncap_first}FormSchema, showActionButtonGroup: false, + baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}} }); /** *初始化加载数据 @@ -30,12 +38,19 @@ res.success && setFieldsValue({...res.result[0]}); }) } + setProps({disabled: props.disabled}) } /** *获取表单数据 */ function getFormData(){ - return [getFieldsValue()]; + let formData = getFieldsValue(); + Object.keys(formData).map(k=>{ + if(formData[k] instanceof Array){ + formData[k] = formData[k].join(',') + } + }); + return [formData]; } /** *表单校验 diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index 98092f3..79b8d13 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -78,11 +78,11 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [ { title: '${col.filedComment}', key: '${col.fieldName}', -<#if col.classType =='date'> +<#if col.fieldType =='date'> type: JVxeTypes.date, -<#elseif col.classType =='datetime'> +<#elseif col.fieldType =='datetime'> type: JVxeTypes.datetime, -<#elseif "int,decimal,double,"?contains(col.classType)> +<#elseif "int,decimal,double,"?contains(col.fieldType)> type: JVxeTypes.inputNumber, <#else> type: JVxeTypes.input, diff --git a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi index 8b14748..8d8ac1c 100644 --- a/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi +++ b/jeecg-boot/jeecg-boot-module-system/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue3/${entityName}__data.tsi @@ -103,7 +103,11 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [ <#if po.fieldType =='date'> component: 'DatePicker', <#elseif po.fieldType =='datetime'> - component: 'TimePicker', + component: 'DatePicker', + componentProps: { + showTime: true, + valueFormat: 'YYYY-MM-DD hh:mm:ss', + }, <#elseif "int,decimal,double,"?contains(po.fieldType)> component: 'InputNumber', <#else> -- libgit2 0.22.2