From b7f164082bbc8c3c4f6b51d5b619dfd0a17cbed0 Mon Sep 17 00:00:00 2001 From: xuyuxiang Date: Sun, 15 Jun 2025 23:22:02 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=9B=B4=E6=96=B0=E3=80=91=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=B9=B6=E5=8D=87=E7=BA=A7v3.5.1=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- .../common/enums/CommonGenderEnum.java | 41 ++++ .../listener/CommonDataChangeEventCenter.java | 2 +- .../java/vip/xiaonuo/dev/api/DevDictApi.java | 8 + .../controller/AuthClientController.java | 45 ++++- .../org/service/impl/BizOrgServiceImpl.java | 2 +- .../service/impl/BizPositionServiceImpl.java | 2 +- .../user/service/impl/BizUserServiceImpl.java | 2 +- .../service/impl/ClientUserServiceImpl.java | 4 + .../config/enums/DevConfigCategoryEnum.java | 81 +------- .../service/impl/DevConfigServiceImpl.java | 37 +++- .../dict/provider/DevDictApiProvider.java | 15 ++ .../modular/dict/service/DevDictService.java | 8 + .../dict/service/impl/DevDictServiceImpl.java | 16 ++ .../file/controller/DevFileController.java | 21 +- .../dev/modular/file/entity/DevFile.java | 4 + .../modular/file/service/DevFileService.java | 10 + .../file/service/impl/DevFileServiceImpl.java | 92 ++++++--- .../service/impl/GenBasicServiceImpl.java | 60 ++++-- .../gen/modular/config/entity/GenConfig.java | 4 + .../config/param/GenConfigAddParam.java | 4 + .../config/param/GenConfigEditParam.java | 5 + .../resources/backend/Controller.java.btl | 49 ++++- .../main/resources/backend/EditParam.java.btl | 6 + .../main/resources/backend/Service.java.btl | 31 ++- .../resources/backend/ServiceImpl.java.btl | 189 ++++++++++++++++-- .../src/main/resources/frontend/Api.js.btl | 18 +- .../resources/frontend/importModel.vue.btl | 129 ++++++++++++ .../src/main/resources/frontend/index.vue.btl | 41 +++- .../src/main/resources/sqlend/Mysql.sql.btl | 13 +- .../src/main/resources/sqlend/Oracle.sql.btl | 13 +- .../org/service/impl/SysOrgServiceImpl.java | 2 +- .../service/impl/SysPositionServiceImpl.java | 2 +- .../provider/SysRelationApiProvider.java | 20 +- .../sys/modular/resource/entity/SysMenu.java | 8 + .../resource/enums/SysMenuWhetherEnum.java | 37 ++++ .../resource/param/menu/SysMenuAddParam.java | 8 + .../resource/param/menu/SysMenuEditParam.java | 8 + .../service/impl/SysButtonServiceImpl.java | 6 +- .../service/impl/SysMenuServiceImpl.java | 2 +- .../service/impl/SysModuleServiceImpl.java | 2 +- .../role/controller/SysRoleController.java | 1 + .../role/param/SysRoleGrantUserParam.java | 3 + .../role/service/impl/SysRoleServiceImpl.java | 8 +- .../user/param/SysUserBindEmailParam.java | 5 - .../user/service/impl/SysUserServiceImpl.java | 35 +++- .../xiaonuo/core/config/GlobalConfigure.java | 14 +- .../src/main/resources/_sql/snowy_mysql.sql | 4 + 48 files changed, 911 insertions(+), 210 deletions(-) create mode 100644 snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java create mode 100644 snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java diff --git a/README.md b/README.md index 5827e91e..e677fdec 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,9 @@ snowy QQ技术群:732230670(已满)、685395081 -微信技术群:因群达到200人以上,需加微信拉群 +微信技术群: + +因群达到200人以上,需加微信拉群,禁止群内艾特群主及管理员,私信提问技术问题无时间精力回答(免开尊口),请群内互动互助才是建群的意义,否则我认为你没有加群的必要 diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java b/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java new file mode 100644 index 00000000..15171076 --- /dev/null +++ b/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonGenderEnum.java @@ -0,0 +1,41 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.common.enums; + +import lombok.Getter; +import vip.xiaonuo.common.exception.CommonException; + +/** + * 通用性别枚举 + * + * @author xuyuxiang + * @date 2022/7/13 17:48 + **/ +@Getter +public enum CommonGenderEnum { + + /** 未知 */ + UNKNOWN("未知"), + + /** 男 */ + MAN("男"), + + /** 女 */ + WOMAN("女"); + + private final String value; + + CommonGenderEnum(String value) { + this.value = value.toLowerCase(); + } +} diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java b/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java index ef29901d..b36bb2cb 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java @@ -191,7 +191,7 @@ public class CommonDataChangeEventCenter { * @author xuyuxiang * @date 2023/3/3 10:22 **/ - public static void doDeleteWithDataId(String dataType, List dataIdList) { + public static void doDeleteWithDataIdList(String dataType, List dataIdList) { for (CommonDataChangeListener listener : listenerList) { listener.doDeleteWithDataIdList(dataType, dataIdList); } diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java index 36a9d904..07b8f3b8 100644 --- a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevDictApi.java @@ -19,4 +19,12 @@ package vip.xiaonuo.dev.api; * @date 2022/9/2 15:58 */ public interface DevDictApi { + + /** + * 根据类型跟子类型获得翻译后的label + * + * @author yubaoshan + * @date 2025/6/6 13:04 + */ + String getDictLabel(String typeCode, String value); } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java index 5b20dbc5..75a13127 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java @@ -26,10 +26,7 @@ import vip.xiaonuo.auth.core.annotation.SaClientCheckLogin; import vip.xiaonuo.auth.core.enums.SaClientTypeEnum; import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser; import vip.xiaonuo.auth.core.util.StpClientUtil; -import vip.xiaonuo.auth.modular.login.param.AuthAccountPasswordLoginParam; -import vip.xiaonuo.auth.modular.login.param.AuthGetPhoneValidCodeParam; -import vip.xiaonuo.auth.modular.login.param.AuthPhoneValidCodeLoginParam; -import vip.xiaonuo.auth.modular.login.param.AuthRegisterParam; +import vip.xiaonuo.auth.modular.login.param.*; import vip.xiaonuo.auth.modular.login.result.AuthPicValidCodeResult; import vip.xiaonuo.auth.modular.login.service.AuthService; import vip.xiaonuo.common.pojo.CommonResult; @@ -65,25 +62,38 @@ public class AuthClientController { } /** - * C端获取手机验证码 + * C端获取手机登录验证码 * * @author xuyuxiang * @date 2022/7/8 9:26 **/ @ApiOperationSupport(order = 2) - @Operation(summary = "C端获取手机验证码") + @Operation(summary = "C端获取手机登录验证码") @GetMapping("/auth/c/getPhoneValidCode") public CommonResult getPhoneValidCode(@Valid AuthGetPhoneValidCodeParam authGetPhoneValidCodeParam) { return CommonResult.data(authService.getPhoneValidCode(authGetPhoneValidCodeParam, SaClientTypeEnum.C.getValue())); } + /** + * C端获取邮箱登录验证码 + * + * @author xuyuxiang + * @date 2022/7/8 9:26 + **/ + @ApiOperationSupport(order = 3) + @Operation(summary = "C端获取邮箱登录验证码") + @GetMapping("/auth/c/getEmailValidCode") + public CommonResult getEmailValidCode(@Valid AuthGetEmailValidCodeParam authGetEmailValidCodeParam) { + return CommonResult.data(authService.getEmailValidCode(authGetEmailValidCodeParam, SaClientTypeEnum.C.getValue())); + } + /** * C端账号密码登录 * * @author xuyuxiang * @date 2021/10/15 13:12 **/ - @ApiOperationSupport(order = 3) + @ApiOperationSupport(order = 4) @Operation(summary = "C端账号密码登录") @PostMapping("/auth/c/doLogin") public CommonResult doLogin(@RequestBody @Valid AuthAccountPasswordLoginParam authAccountPasswordLoginParam) { @@ -96,20 +106,33 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ - @ApiOperationSupport(order = 4) + @ApiOperationSupport(order = 5) @Operation(summary = "C端手机验证码登录") @PostMapping("/auth/c/doLoginByPhone") public CommonResult doLoginByPhone(@RequestBody @Valid AuthPhoneValidCodeLoginParam authPhoneValidCodeLoginParam) { return CommonResult.data(authService.doLoginByPhone(authPhoneValidCodeLoginParam, SaClientTypeEnum.C.getValue())); } + /** + * C端邮箱验证码登录 + * + * @author xuyuxiang + * @date 2021/10/15 13:12 + **/ + @ApiOperationSupport(order = 6) + @Operation(summary = "C端邮箱验证码登录") + @PostMapping("/auth/c/doLoginByEmail") + public CommonResult doLoginByEmail(@RequestBody @Valid AuthEmailValidCodeLoginParam authEmailValidCodeLoginParam) { + return CommonResult.data(authService.doLoginByEmail(authEmailValidCodeLoginParam, SaClientTypeEnum.C.getValue())); + } + /** * C端退出 * * @author xuyuxiang * @date 2021/10/15 13:12 **/ - @ApiOperationSupport(order = 5) + @ApiOperationSupport(order = 7) @Operation(summary = "C端退出") @SaClientCheckLogin @GetMapping("/auth/c/doLogout") @@ -124,7 +147,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ - @ApiOperationSupport(order = 6) + @ApiOperationSupport(order = 8) @Operation(summary = "C端获取用户信息") @SaClientCheckLogin @GetMapping("/auth/c/getLoginUser") @@ -138,7 +161,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ - @ApiOperationSupport(order = 7) + @ApiOperationSupport(order = 9) @Operation(summary = "C端注册") @PostMapping("/auth/c/register") public CommonResult register(@RequestBody @Valid AuthRegisterParam authRegisterParam) { diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java index 1449431a..6545e0f5 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java @@ -242,7 +242,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme this.removeByIds(toDeleteOrgIdList); // 发布删除事件 - CommonDataChangeEventCenter.doDeleteWithDataId(BizDataTypeEnum.ORG.getValue(), toDeleteOrgIdList); + CommonDataChangeEventCenter.doDeleteWithDataIdList(BizDataTypeEnum.ORG.getValue(), toDeleteOrgIdList); } } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java index a1967ee8..95233c60 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java @@ -190,7 +190,7 @@ public class BizPositionServiceImpl extends ServiceImpl impl bizUserExtService.remove(new LambdaQueryWrapper().in(BizUserExt::getUserId, bizUserIdList)); // 发布删除事件 - CommonDataChangeEventCenter.doDeleteWithDataId(BizDataTypeEnum.USER.getValue(), bizUserIdList); + CommonDataChangeEventCenter.doDeleteWithDataIdList(BizDataTypeEnum.USER.getValue(), bizUserIdList); } } diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java index 72c44791..390bc212 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java @@ -54,6 +54,7 @@ import vip.xiaonuo.client.modular.user.service.ClientUserExtService; import vip.xiaonuo.client.modular.user.service.ClientUserPasswordService; import vip.xiaonuo.client.modular.user.service.ClientUserService; import vip.xiaonuo.common.cache.CommonCacheOperator; +import vip.xiaonuo.common.enums.CommonGenderEnum; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; @@ -942,6 +943,7 @@ public class ClientUserServiceImpl extends ServiceImpl implements DevConfigService { + /** 缓存前缀 */ private static final String CONFIG_CACHE_KEY = "dev-config:"; + /** B端注册是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B"; + + /** C端注册是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C"; + + /** B端手机号登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B"; + + /** C端手机号登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C"; + + /** B端邮箱登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B"; + + /** C端邮箱登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C"; + @Resource private CommonCacheOperator commonCacheOperator; @@ -91,9 +111,20 @@ public class DevConfigServiceImpl extends ServiceImpl sysBaseList() { - DevConfigListParam devConfigListParam = new DevConfigListParam(); - devConfigListParam.setCategory(DevConfigCategoryEnum.SYS_BASE.getValue()); - return this.list(devConfigListParam); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + // 查询部分字段 + lambdaQueryWrapper.select(DevConfig::getId, DevConfig::getConfigKey, DevConfig::getConfigValue, + DevConfig::getCategory, DevConfig::getSortCode, DevConfig::getRemark); + // 类型为系统基础的 + lambdaQueryWrapper.eq(DevConfig::getCategory, DevConfigCategoryEnum.SYS_BASE.getValue()); + // 或key为特殊的几个 + lambdaQueryWrapper.or().in(DevConfig::getConfigKey, CollectionUtil.newArrayList(SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B_KEY, + SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C_KEY, + SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B_KEY, + SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C_KEY, + SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B_KEY, + SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C_KEY)); + return this.list(lambdaQueryWrapper); } @Override diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java index e9a5df0d..112f7fa3 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/provider/DevDictApiProvider.java @@ -12,8 +12,10 @@ */ package vip.xiaonuo.dev.modular.dict.provider; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import vip.xiaonuo.dev.api.DevDictApi; +import vip.xiaonuo.dev.modular.dict.service.DevDictService; /** * 字典API接口实现类 @@ -23,4 +25,17 @@ import vip.xiaonuo.dev.api.DevDictApi; */ @Service public class DevDictApiProvider implements DevDictApi { + + @Resource + private DevDictService devDictService; + + /** + * 根据类型跟子类型获得翻译后的label + * + * @author yubaoshan + * @date 2025/6/6 13:04 + */ + public String getDictLabel(String typeCode, String value) { + return devDictService.getDictLabel(typeCode, value); + } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java index c45ca38e..ded44182 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/DevDictService.java @@ -91,4 +91,12 @@ public interface DevDictService extends IService { * @date 2022/4/24 21:18 */ DevDict queryEntity(String id); + + /** + * 根据类型跟子类型获得翻译后的label + * + * @author yubaoshan + * @date 2025/6/6 13:04 + */ + String getDictLabel(String typeCode, String value); } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java index 50a773fb..5eead300 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java @@ -235,4 +235,20 @@ public class DevDictServiceImpl extends ServiceImpl impl return null; }); } + + @Override + public String getDictLabel(String typeCode, String value) { + List devDictList = this.list(new LambdaQueryWrapper().eq(DevDict::getDictValue, typeCode)); + if (ObjectUtil.isNotEmpty(devDictList) && devDictList.size() == 1) { + DevDict devDictClone = devDictList.get(0); + DevDict devDict = this.getOne(new LambdaQueryWrapper().eq(DevDict::getParentId, devDictClone.getId()) + .eq(DevDict::getDictValue, value)); + if (ObjectUtil.isNotEmpty(devDict)) { + return devDict.getDictLabel(); + } else { + return null; + } + } + return null; + } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java index f4d81e1c..e2fa8863 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java @@ -240,13 +240,27 @@ public class DevFileController { devFileService.download(devFileIdParam, response); } + /** + * 下载文件 + * + * @author xuyuxiang + * @date 2022/6/21 15:44 + **/ + @ApiOperationSupport(order = 14) + @Operation(summary = "授权下载文件") + @CommonLog("授权下载文件") + @GetMapping(value = "/dev/file/authDownload", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public void authDownload(@Valid DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException { + devFileService.authDownload(devFileIdParam, response); + } + /** * 删除文件 * * @author xuyuxiang * @date 2022/4/24 20:00 */ - @ApiOperationSupport(order = 14) + @ApiOperationSupport(order = 15) @Operation(summary = "删除文件") @CommonLog("删除文件") @PostMapping(value = "/dev/file/delete") @@ -262,6 +276,7 @@ public class DevFileController { * @author 每天一点 * @date 2025/4/06 20:25 */ + @ApiOperationSupport(order = 16) @Operation(summary = "物理删除文件") @CommonLog("物理删除文件") @PostMapping(value = "/dev/file/deleteAbsolute") @@ -276,7 +291,7 @@ public class DevFileController { * @author xuyuxiang * @date 2022/6/21 15:44 **/ - @ApiOperationSupport(order = 15) + @ApiOperationSupport(order = 17) @Operation(summary = "获取文件详情") @GetMapping("/dev/file/detail") public CommonResult detail(@Valid DevFileIdParam devFileIdParam) { @@ -289,7 +304,7 @@ public class DevFileController { * @author yubaoshan * @date 2024/6/9 23:52 **/ - @ApiOperationSupport(order = 16) + @ApiOperationSupport(order = 18) @Operation(summary = "根据文件url集合获取文件集合") @PostMapping("/dev/file/getFileListByUrlList") public CommonResult> getFileListByUrlList(@RequestBody @Valid DevFileUrlListParam devFileUrlListParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java index 0ddc6316..7ee22077 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java @@ -73,6 +73,10 @@ public class DevFile extends CommonEntity { @Schema(description = "文件下载路径") private String downloadPath; + /** 文件下载是否需要授权 */ + @Schema(description = "文件下载是否需要授权") + private Boolean isDownloadAuth; + /** 图片缩略图 */ @Schema(description = "图片缩略图") private String thumbnail; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java index fc2e6041..fba70724 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java @@ -73,6 +73,16 @@ public interface DevFileService extends IService { **/ void download(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException; + + /** + * 授权下载文件 + * + * @author xuyuxiang + * @date 2022/6/21 15:44 + **/ + void authDownload(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException; + + /** * 删除文件 * diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java index 5f8ec4c9..0c864f2d 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java @@ -18,9 +18,11 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.img.ImgUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; @@ -71,12 +73,12 @@ public class DevFileServiceImpl extends ServiceImpl impl @Override public String uploadReturnId(String engine, MultipartFile file) { - return this.storageFile(engine, file, true); + return this.storageFile(engine, file, true, true); } @Override public String uploadReturnUrl(String engine, MultipartFile file) { - return this.storageFile(engine, file, false); + return this.storageFile(engine, file, false, false); } @Override @@ -105,6 +107,33 @@ public class DevFileServiceImpl extends ServiceImpl impl @Override public void download(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException { + unifiedDownload(devFileIdParam, response, false); +// DevFile devFile; +// try { +// devFile = this.queryEntity(devFileIdParam.getId()); +// } catch (Exception e) { +// CommonResponseUtil.renderError(response, e.getMessage()); +// return; +// } +// if(!devFile.getEngine().equals(DevFileEngineTypeEnum.LOCAL.getValue())) { +// CommonResponseUtil.renderError(response, "非本地文件不支持此方式下载,id值为:" + devFile.getId()); +// return; +// } +// File file = FileUtil.file(devFile.getStoragePath()); +// if(!FileUtil.exist(file)) { +// CommonResponseUtil.renderError(response, "找不到存储的文件,id值为:" + devFile.getId()); +// return; +// } +// CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response); + } + + @Override + public void authDownload(DevFileIdParam devFileIdParam, HttpServletResponse response) throws IOException { + unifiedDownload(devFileIdParam, response, true); + } + + // 统一下载 + private void unifiedDownload(DevFileIdParam devFileIdParam, HttpServletResponse response, boolean isDownloadAuth) throws IOException{ DevFile devFile; try { devFile = this.queryEntity(devFileIdParam.getId()); @@ -112,16 +141,21 @@ public class DevFileServiceImpl extends ServiceImpl impl CommonResponseUtil.renderError(response, e.getMessage()); return; } - if(!devFile.getEngine().equals(DevFileEngineTypeEnum.LOCAL.getValue())) { - CommonResponseUtil.renderError(response, "非本地文件不支持此方式下载,id值为:" + devFile.getId()); + if (BooleanUtil.isTrue(devFile.getIsDownloadAuth()) && !isDownloadAuth){ + CommonResponseUtil.renderError(response, "该文件需要授权下载,请使用授权接口authDownload进行下载!"); return; } - File file = FileUtil.file(devFile.getStoragePath()); - if(!FileUtil.exist(file)) { - CommonResponseUtil.renderError(response, "找不到存储的文件,id值为:" + devFile.getId()); - return; + if(devFile.getEngine().equals(DevFileEngineTypeEnum.LOCAL.getValue())) { + File file = FileUtil.file(devFile.getStoragePath()); + if(!FileUtil.exist(file)) { + CommonResponseUtil.renderError(response, "找不到存储的文件,id值为:" + devFile.getId()); + return; + } + CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response); + } else { + String storagePath = devFile.getStoragePath(); + CommonDownloadUtil.download(devFile.getName(), HttpUtil.downloadBytes(storagePath), response); } - CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response); } @Transactional(rollbackFor = Exception.class) @@ -165,7 +199,7 @@ public class DevFileServiceImpl extends ServiceImpl impl * @author xuyuxiang * @date 2022/6/16 16:24 **/ - private String storageFile(String engine, MultipartFile file, boolean returnFileId) { + private String storageFile(String engine, MultipartFile file, boolean returnFileId, Boolean isDownloadAuth) { // 如果引擎为空,默认使用本地 if(ObjectUtil.isEmpty(engine)) { @@ -241,20 +275,32 @@ public class DevFileServiceImpl extends ServiceImpl impl // 定义下载地址 String downloadUrl; - - // 下载路径,注意:本地文件下载地址设置为下载接口地址 + 文件id - if(engine.equals(DevFileEngineTypeEnum.LOCAL.getValue())) { - String apiUrl = commonProperties.getBackendUrl(); - if(ObjectUtil.isEmpty(apiUrl)) { - throw new CommonException("后端域名地址未正确配置:snowy.config.common.backend-url为空"); - } - downloadUrl= apiUrl + "/dev/file/download?id=" + fileId; - devFile.setDownloadPath(downloadUrl); - } else { - // 阿里云、腾讯云、MINIO可以直接使用存储地址(公网)作为下载地址 - downloadUrl= storageUrl; - devFile.setDownloadPath(devFile.getStoragePath()); + String apiUrl = commonProperties.getBackendUrl(); + if(ObjectUtil.isEmpty(apiUrl)) { + throw new CommonException("后端域名地址未正确配置:snowy.config.common.backend-url为空"); } + if (BooleanUtil.isTrue(isDownloadAuth)){ + downloadUrl= apiUrl + "/dev/file/authDownload?id=" + fileId + "&tenCode=" + tenApi.getCurrentTenCode() + "&token="; + }else { + downloadUrl= apiUrl + "/dev/file/download?id=" + fileId; + } + devFile.setDownloadPath(downloadUrl); + +// // 下载路径,注意:本地文件下载地址设置为下载接口地址 + 文件id +// if(engine.equals(DevFileEngineTypeEnum.LOCAL.getValue())) { +// String apiUrl = commonProperties.getBackendUrl(); +// if(ObjectUtil.isEmpty(apiUrl)) { +// throw new CommonException("后端域名地址未正确配置:snowy.config.common.backend-url为空"); +// } +// downloadUrl= apiUrl + "/dev/file/download?id=" + fileId + "&tenCode=" + tenApi.getCurrentTenCode(); +// devFile.setDownloadPath(downloadUrl); +// } else { +// // 阿里云、腾讯云、MINIO可以直接使用存储地址(公网)作为下载地址 +// downloadUrl= storageUrl; +// devFile.setDownloadPath(devFile.getStoragePath()); +// } + + devFile.setIsDownloadAuth(isDownloadAuth); this.save(devFile); diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java index 393afd41..3990ef4e 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java +++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/service/impl/GenBasicServiceImpl.java @@ -98,7 +98,8 @@ public class GenBasicServiceImpl extends ServiceImpl i private static final List GEN_FRONT_FILE_LIST = CollectionUtil.newArrayList( JSONUtil.createObj().set("name", "Api.js.btl").set("path", "api"), JSONUtil.createObj().set("name", "form.vue.btl").set("path", "views"), - JSONUtil.createObj().set("name", "index.vue.btl").set("path", "views")); + JSONUtil.createObj().set("name", "index.vue.btl").set("path", "views"), + JSONUtil.createObj().set("name", "importModel.vue.btl").set("path", "views")); private static final List GEN_MOBILE_FILE_LIST = CollectionUtil.newArrayList( JSONUtil.createObj().set("name", "page.json.btl"), @@ -242,6 +243,7 @@ public class GenBasicServiceImpl extends ServiceImpl i } addParam.setWhetherRetract(GenYesNoEnum.N.getValue()); addParam.setWhetherRequired(GenYesNoEnum.N.getValue()); + addParam.setWhetherUnique(GenYesNoEnum.N.getValue()); addParam.setQueryWhether(GenYesNoEnum.N.getValue()); addParam.setSortCode(i); GenConfig genConfig = BeanUtil.toBean(addParam, GenConfig.class); @@ -330,27 +332,30 @@ public class GenBasicServiceImpl extends ServiceImpl i schema = metaData.getUserName(); } List columns = new ArrayList<>(); - rs = metaData.getColumns(null, schema, genBasicTableColumnParam.getTableName(), "%"); + rs = metaData.getColumns(conn.getCatalog(), schema, genBasicTableColumnParam.getTableName(), "%"); if(!rs.isBeforeFirst()) { - rs = metaData.getColumns(null, schema, genBasicTableColumnParam.getTableName().toLowerCase(), "%"); + rs = metaData.getColumns(conn.getCatalog(), schema, genBasicTableColumnParam.getTableName().toLowerCase(), "%"); } while (rs.next()) { String columnName = rs.getString("COLUMN_NAME").toUpperCase(); - GenBasicTableColumnResult genBasicTableColumnResult = new GenBasicTableColumnResult(); - genBasicTableColumnResult.setColumnName(columnName); - String remarks = rs.getString("REMARKS"); - if(ObjectUtil.isEmpty(remarks)) { - genBasicTableColumnResult.setColumnRemark(columnName); - } else { - genBasicTableColumnResult.setColumnRemark(remarks); + boolean exist = columns.stream().anyMatch(dbsTableColumnResult -> dbsTableColumnResult.getColumnName().equals(columnName)); + if(!exist) { + GenBasicTableColumnResult genBasicTableColumnResult = new GenBasicTableColumnResult(); + genBasicTableColumnResult.setColumnName(columnName); + String remarks = rs.getString("REMARKS"); + if(ObjectUtil.isEmpty(remarks)) { + genBasicTableColumnResult.setColumnRemark(columnName); + } else { + genBasicTableColumnResult.setColumnRemark(remarks); + } + String typeName = rs.getString("TYPE_NAME").toUpperCase(); + if(ObjectUtil.isEmpty(typeName)) { + genBasicTableColumnResult.setTypeName("NONE"); + } else { + genBasicTableColumnResult.setTypeName(typeName); + } + columns.add(genBasicTableColumnResult); } - String typeName = rs.getString("TYPE_NAME").toUpperCase(); - if(ObjectUtil.isEmpty(typeName)) { - genBasicTableColumnResult.setTypeName("NONE"); - } else { - genBasicTableColumnResult.setTypeName(typeName); - } - columns.add(genBasicTableColumnResult); } return columns; } catch (SQLException sqlException) { @@ -675,6 +680,10 @@ public class GenBasicServiceImpl extends ServiceImpl i bindingJsonObject.set("deleteButtonId", IdWorker.getIdStr()); // 批量删除按钮ID bindingJsonObject.set("batchDeleteButtonId", IdWorker.getIdStr()); + // 导入按钮ID + bindingJsonObject.set("importButtonId", IdWorker.getIdStr()); + // 导出按钮ID + bindingJsonObject.set("exportButtonId", IdWorker.getIdStr()); // 作者 bindingJsonObject.set("authorName", genBasic.getAuthorName()); // 生成时间 @@ -697,6 +706,7 @@ public class GenBasicServiceImpl extends ServiceImpl i configItem.set("needPage", false); configItem.set("needPageType", "none"); configItem.set("required", true); + configItem.set("unique", true); configItem.set("needTableId", true); bindingJsonObject.set("dbTableKeyJavaType", genConfig.getFieldJavaType()); bindingJsonObject.set("dbTableKeyRemark", genConfig.getFieldRemark()); @@ -712,6 +722,7 @@ public class GenBasicServiceImpl extends ServiceImpl i configItem.set("needPage", false); configItem.set("needPageType", "none"); configItem.set("required", false); + configItem.set("unique", false); configItem.set("needTableId", false); } else { boolean needAddAndUpdate = genConfig.getWhetherAddUpdate().equalsIgnoreCase(GenYesNoEnum.Y.getValue()); @@ -720,6 +731,7 @@ public class GenBasicServiceImpl extends ServiceImpl i configItem.set("needPage", genConfig.getQueryWhether().equalsIgnoreCase(GenYesNoEnum.Y.getValue())); configItem.set("needPageType", genConfig.getQueryType()); configItem.set("required", genConfig.getWhetherRequired().equalsIgnoreCase(GenYesNoEnum.Y.getValue())); + configItem.set("unique", ObjectUtil.isNotEmpty(genConfig.getWhetherUnique()) && genConfig.getWhetherUnique().equalsIgnoreCase(GenYesNoEnum.Y.getValue())); configItem.set("needTableId", false); } } @@ -754,6 +766,20 @@ public class GenBasicServiceImpl extends ServiceImpl i }); // 配置信息 bindingJsonObject.set("configList", configList); + // 获取必填字段 + List requiredFieldList = configList.stream().filter(configItem -> configItem.getBool("required")).toList(); + // 必填字段列表 + bindingJsonObject.set("requiredFieldList", requiredFieldList); + // 必填字段字符串 + bindingJsonObject.set("requiredFieldStr", StrUtil.join(StrUtil.COMMA + " ", requiredFieldList.stream().map(configItem -> + configItem.getStr("fieldNameCamelCase")).collect(Collectors.toList()))); + // 获取唯一字段 + List uniqueFieldList = configList.stream().filter(configItem -> configItem.getBool("unique")).toList(); + // 唯一字段列表 + bindingJsonObject.set("uniqueFieldList", uniqueFieldList); + // 唯一字段字符串 + bindingJsonObject.set("uniqueFieldStr", StrUtil.join(StrUtil.COMMA + " ", uniqueFieldList.stream().map(configItem -> + configItem.getStr("fieldNameCamelCase")).collect(Collectors.toList()))); // 有排序字段 bindingJsonObject.set("hasSortCodeField", hasSortCodeField.get()); return bindingJsonObject; diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java index 35111b1c..15427a6e 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java +++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/entity/GenConfig.java @@ -81,6 +81,10 @@ public class GenConfig extends CommonEntity { @Schema(description = "必填") private String whetherRequired; + /** 唯一 */ + @Schema(description = "唯一") + private String whetherUnique; + /** 查询 */ @Schema(description = "查询") private String queryWhether; diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java index 2d5feffa..8ac6197a 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java +++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigAddParam.java @@ -80,6 +80,10 @@ public class GenConfigAddParam { @Schema(description = "必填") private String whetherRequired; + /** 唯一 */ + @Schema(description = "唯一") + private String whetherUnique; + /** 查询 */ @Schema(description = "查询") private String queryWhether; diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java index 1485f30d..3f014042 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java +++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/config/param/GenConfigEditParam.java @@ -91,6 +91,11 @@ public class GenConfigEditParam { @NotBlank(message = "whetherRequired不能为空") private String whetherRequired; + /** 唯一 */ + @Schema(description = "唯一") + @NotBlank(message = "whetherUnique不能为空") + private String whetherUnique; + /** 查询 */ @Schema(description = "查询", requiredMode = Schema.RequiredMode.REQUIRED) @NotBlank(message = "queryWhether不能为空") diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl index 2c5356dd..5416802c 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Controller.java.btl @@ -13,14 +13,15 @@ package ${packageName}.${moduleName}.modular.${busName}.controller; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import ${packageName}.common.annotation.CommonLog; import ${packageName}.common.pojo.CommonResult; import ${packageName}.${moduleName}.modular.${busName}.entity.${className}; @@ -33,6 +34,7 @@ import ${packageName}.${moduleName}.modular.${busName}.service.${className}Servi import jakarta.annotation.Resource; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; +import java.io.IOException; import java.util.List; /** @@ -120,4 +122,43 @@ public class ${className}Controller { public CommonResult<${className}> detail(@Valid ${className}IdParam ${classNameFirstLower}IdParam) { return CommonResult.data(${classNameFirstLower}Service.detail(${classNameFirstLower}IdParam)); } + + /** + * 下载${functionName}导入模板 + * + * @author ${authorName} + * @date ${genTime} + */ + @Operation(summary = "下载${functionName}导入模板") + @GetMapping(value = "/${moduleName}/${busName}/downloadImportTemplate", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public void downloadImportTemplate(HttpServletResponse response) throws IOException { + ${classNameFirstLower}Service.downloadImportTemplate(response); + } + + /** + * 导入${functionName} + * + * @author ${authorName} + * @date ${genTime} + */ + @Operation(summary = "导入${functionName}") + @CommonLog("导入${functionName}") + @SaCheckPermission("/${moduleName}/${busName}/importData") + @PostMapping("/${moduleName}/${busName}/importData") + public CommonResult importData(@RequestPart("file") MultipartFile file) { + return CommonResult.data(${classNameFirstLower}Service.importData(file)); + } + + /** + * 导出${functionName} + * + * @author ${authorName} + * @date ${genTime} + */ + @Operation(summary = "导出${functionName}") + @SaCheckPermission("/${moduleName}/${busName}/exportData") + @PostMapping(value = "/${moduleName}/${busName}/exportData", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public void exportData(@RequestBody List<${className}IdParam> ${classNameFirstLower}IdParamList, HttpServletResponse response) throws IOException { + ${classNameFirstLower}Service.exportData(${classNameFirstLower}IdParamList, response); + } } diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl index e2bfa400..69cea808 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/EditParam.java.btl @@ -12,6 +12,8 @@ */ package ${packageName}.${moduleName}.modular.${busName}.param; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; @@ -34,6 +36,10 @@ public class ${className}EditParam { <% for(var i = 0; i < configList.~size; i++) { %> <% if(configList[i].needEdit) { %> /** ${configList[i].fieldRemark} */ + <% if(configList[i].fieldJavaType == 'Date') { %> + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + <% } else { %><% } %> + @ExcelProperty("${configList[i].fieldRemark}") @Schema(description = "${configList[i].fieldRemark}"<% if(configList[i].required) { %>, requiredMode = Schema.RequiredMode.REQUIRED<% } %>) <% if(configList[i].required) { %> <% if(configList[i].fieldJavaType == 'String') { %>@NotBlank<% } else { %>@NotNull<% } %>(message = "${configList[i].fieldNameCamelCase}不能为空") diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl index e8daf4d5..3b229a43 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/Service.java.btl @@ -12,14 +12,17 @@ */ package ${packageName}.${moduleName}.modular.${busName}.service; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.multipart.MultipartFile; import ${packageName}.${moduleName}.modular.${busName}.entity.${className}; import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam; import ${packageName}.${moduleName}.modular.${busName}.param.${className}EditParam; import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam; import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam; - +import java.io.IOException; import java.util.List; /** @@ -76,5 +79,29 @@ public interface ${className}Service extends IService<${className}> { * @author ${authorName} * @date ${genTime} **/ - ${className} queryEntity(String id); + ${className} queryEntity(String ${dbTableKeyCamelCase}); + + /** + * 下载${functionName}导入模板 + * + * @author ${authorName} + * @date ${genTime} + */ + void downloadImportTemplate(HttpServletResponse response) throws IOException; + + /** + * 导入${functionName} + * + * @author ${authorName} + * @date ${genTime} + **/ + JSONObject importData(MultipartFile file); + + /** + * 导出${functionName} + * + * @author ${authorName} + * @date ${genTime} + */ + void exportData(List<${className}IdParam> ${classNameFirstLower}IdParamList, HttpServletResponse response) throws IOException; } diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl index ddac0796..1ed78f4f 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/backend/ServiceImpl.java.btl @@ -13,17 +13,31 @@ package ${packageName}.${moduleName}.modular.${busName}.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import ${packageName}.common.enums.CommonSortOrderEnum; import ${packageName}.common.exception.CommonException; import ${packageName}.common.page.CommonPageRequest; +import java.math.BigDecimal; +import java.util.Date; import ${packageName}.${moduleName}.modular.${busName}.entity.${className}; import ${packageName}.${moduleName}.modular.${busName}.mapper.${className}Mapper; import ${packageName}.${moduleName}.modular.${busName}.param.${className}AddParam; @@ -32,6 +46,11 @@ import ${packageName}.${moduleName}.modular.${busName}.param.${className}IdParam import ${packageName}.${moduleName}.modular.${busName}.param.${className}PageParam; import ${packageName}.${moduleName}.modular.${busName}.service.${className}Service; +import vip.xiaonuo.common.util.CommonDownloadUtil; +import vip.xiaonuo.common.util.CommonResponseUtil; + +import java.io.File; +import java.io.IOException; import java.util.List; /** @@ -77,18 +96,28 @@ public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${c @Override public void add(${className}AddParam ${classNameFirstLower}AddParam) { ${className} ${classNameFirstLower} = BeanUtil.toBean(${classNameFirstLower}AddParam, ${className}.class); + <% for(var i = 0; i < uniqueFieldList.~size; i++) { %> + <% if(!uniqueFieldList[i].needTableId) { %> + if(this.count(new LambdaQueryWrapper<${className}>().eq(${className}::get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}, ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}())) > 0) { + throw new CommonException("存在重复的${uniqueFieldList[i].fieldRemark},值为:{}", ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()); + } + <% } %> + <% } %> this.save(${classNameFirstLower}); } @Transactional(rollbackFor = Exception.class) @Override public void edit(${className}EditParam ${classNameFirstLower}EditParam) { - <% for(var i = 0; i < configList.~size; i++) { %> - <% if(configList[i].needTableId) { %> - ${className} ${classNameFirstLower} = this.queryEntity(${classNameFirstLower}EditParam.get${configList[i].fieldNameCamelCaseFirstUpper}()); - <% } %> - <% } %> + ${className} ${classNameFirstLower} = this.queryEntity(${classNameFirstLower}EditParam.get${dbTableKeyFirstUpper}()); BeanUtil.copyProperties(${classNameFirstLower}EditParam, ${classNameFirstLower}); + <% for(var i = 0; i < uniqueFieldList.~size; i++) { %> + <% if(!uniqueFieldList[i].needTableId) { %> + if(this.count(new LambdaQueryWrapper<${className}>().ne(${className}::get${dbTableKeyFirstUpper}, ${classNameFirstLower}.get${dbTableKeyFirstUpper}()).eq(${className}::get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}, ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}())) > 0) { + throw new CommonException("存在重复的${uniqueFieldList[i].fieldRemark},值为:{}", ${classNameFirstLower}.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()); + } + <% } %> + <% } %> this.updateById(${classNameFirstLower}); } @@ -96,20 +125,129 @@ public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${c @Override public void delete(List<${className}IdParam> ${classNameFirstLower}IdParamList) { // 执行删除 - <% for(var i = 0; i < configList.~size; i++) { %> - <% if(configList[i].needTableId) { %> - this.removeByIds(CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${configList[i].fieldNameCamelCaseFirstUpper})); - <% } %> - <% } %> + this.removeByIds(CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${dbTableKeyFirstUpper})); } @Override public ${className} detail(${className}IdParam ${classNameFirstLower}IdParam) { - <% for(var i = 0; i < configList.~size; i++) { %> - <% if(configList[i].needTableId) { %> - return this.queryEntity(${classNameFirstLower}IdParam.get${configList[i].fieldNameCamelCaseFirstUpper}()); - <% } %> + return this.queryEntity(${classNameFirstLower}IdParam.get${dbTableKeyFirstUpper}()); + } + + @Override + public ${className} queryEntity(String ${dbTableKeyCamelCase}) { + ${className} ${classNameFirstLower} = this.getById(${dbTableKeyCamelCase}); + if(ObjectUtil.isEmpty(${classNameFirstLower})) { + throw new CommonException("${functionName}不存在,${dbTableKeyCamelCase}值为:{}", ${dbTableKeyCamelCase}); + } + return ${classNameFirstLower}; + } + + @Override + public void downloadImportTemplate(HttpServletResponse response) throws IOException { + File tempFile = null; + try { + List<${className}EditParam> dataList = CollectionUtil.newArrayList(); + String fileName = "${functionName}导入模板_" + DateUtil.format(DateTime.now(), DatePattern.PURE_DATETIME_PATTERN) + ".xlsx"; + tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName); + EasyExcel.write(tempFile.getPath(), ${className}EditParam.class).sheet("${functionName}").doWrite(dataList); + CommonDownloadUtil.download(tempFile, response); + } catch (Exception e) { + log.error(">>> ${functionName}导入模板下载失败:", e); + CommonResponseUtil.renderError(response, "${functionName}导入模板下载失败"); + } finally { + FileUtil.del(tempFile); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public JSONObject importData(MultipartFile file) { + try { + int successCount = 0; + int errorCount = 0; + JSONArray errorDetail = JSONUtil.createArray(); + // 创建临时文件 + File tempFile = FileUtil.writeBytes(file.getBytes(), FileUtil.file(FileUtil.getTmpDir() + + FileUtil.FILE_SEPARATOR + "${classNameFirstLower}ImportTemplate.xlsx")); + // 读取excel + List<${className}EditParam> ${classNameFirstLower}EditParamList = EasyExcel.read(tempFile).head(${className}EditParam.class).sheet() + .headRowNumber(1).doReadSync(); + List<${className}> allDataList = this.list(); + for (int i = 0; i < ${classNameFirstLower}EditParamList.size(); i++) { + JSONObject jsonObject = this.doImport(allDataList, ${classNameFirstLower}EditParamList.get(i), i); + if(jsonObject.getBool("success")) { + successCount += 1; + } else { + errorCount += 1; + errorDetail.add(jsonObject); + } + } + return JSONUtil.createObj() + .set("totalCount", ${classNameFirstLower}EditParamList.size()) + .set("successCount", successCount) + .set("errorCount", errorCount) + .set("errorDetail", errorDetail); + } catch (Exception e) { + log.error(">>> ${functionName}导入失败:", e); + throw new CommonException("${functionName}导入失败"); + } + } + + public JSONObject doImport(List<${className}> allDataList, ${className}EditParam ${classNameFirstLower}EditParam, int i) { + <% for(var i = 0; i < requiredFieldList.~size; i++) { %> + ${requiredFieldList[i].fieldJavaType} ${requiredFieldList[i].fieldNameCamelCase} = ${classNameFirstLower}EditParam.get${requiredFieldList[i].fieldNameCamelCaseFirstUpper}(); <% } %> + if(ObjectUtil.hasEmpty(${requiredFieldStr})) { + return JSONUtil.createObj().set("index", i + 1).set("success", false).set("msg", "必填字段存在空值"); + } else { + try { + int index = CollStreamUtil.toList(allDataList, ${className}::get${dbTableKeyFirstUpper}).indexOf(${classNameFirstLower}EditParam.get${dbTableKeyFirstUpper}()); + ${className} ${classNameFirstLower}; + boolean isAdd = false; + if(index == -1) { + isAdd = true; + ${classNameFirstLower} = new ${className}(); + } else { + ${classNameFirstLower} = allDataList.get(index); + } + <% if(uniqueFieldList.~size > 1) { %> + if(isAdd) { + <% for(var i = 0; i < uniqueFieldList.~size; i++) { %> + <% if(!uniqueFieldList[i].needTableId) { %> + boolean repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper} = allDataList.stream().anyMatch(tempData -> ObjectUtil + .isNotEmpty(tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()) && tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}().equals(${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}())); + if(repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}) { + return JSONUtil.createObj().set("index", i + 1).set("success", false).set("msg", "新增数据时字段【${uniqueFieldList[i].fieldRemark}(${uniqueFieldList[i].fieldNameCamelCase})】与数据库中数据重复,值为:" + ${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()); + } + <% } %> + <% } %> + } else { + <% for(var i = 0; i < uniqueFieldList.~size; i++) { %> + <% if(!uniqueFieldList[i].needTableId) { %> + boolean repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper} = allDataList.stream().anyMatch(tempData -> ObjectUtil + .isNotEmpty(tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()) && tempData.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}() + .equals(${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()) && !tempData.get${dbTableKeyFirstUpper}().equals(${classNameFirstLower}.get${dbTableKeyFirstUpper}())); + if(repeat${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}) { + return JSONUtil.createObj().set("index", i + 1).set("success", false).set("msg", "更新数据时字段【${uniqueFieldList[i].fieldRemark}(${uniqueFieldList[i].fieldNameCamelCase})】与数据库中数据重复,值为:" + ${classNameFirstLower}EditParam.get${uniqueFieldList[i].fieldNameCamelCaseFirstUpper}()); + } + <% } %> + <% } %> + } + <% } %> + BeanUtil.copyProperties(${classNameFirstLower}EditParam, ${classNameFirstLower}); + if(isAdd) { + allDataList.add(${classNameFirstLower}); + } else { + allDataList.remove(index); + allDataList.add(index, ${classNameFirstLower}); + } + this.saveOrUpdate(${classNameFirstLower}); + return JSONUtil.createObj().set("success", true); + } catch (Exception e) { + log.error(">>> 数据导入异常:", e); + return JSONUtil.createObj().set("success", false).set("index", i + 1).set("msg", "数据导入异常"); + } + } } @Override @@ -120,4 +258,27 @@ public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${c } return ${classNameFirstLower}; } + + @Override + public void exportData(List<${className}IdParam> ${classNameFirstLower}IdParamList, HttpServletResponse response) throws IOException { + File tempFile = null; + try { + List<${className}EditParam> dataList; + if(ObjectUtil.isNotEmpty(${classNameFirstLower}IdParamList)) { + List ${dbTableKeyCamelCase}List = CollStreamUtil.toList(${classNameFirstLower}IdParamList, ${className}IdParam::get${dbTableKeyFirstUpper}); + dataList = BeanUtil.copyToList(this.listByIds(${dbTableKeyCamelCase}List), ${className}EditParam.class); + } else { + dataList = BeanUtil.copyToList(this.list(), ${className}EditParam.class); + } + String fileName = "${functionName}_" + DateUtil.format(DateTime.now(), DatePattern.PURE_DATETIME_PATTERN) + ".xlsx"; + tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName); + EasyExcel.write(tempFile.getPath(), ${className}EditParam.class).sheet("${functionName}").doWrite(dataList); + CommonDownloadUtil.download(tempFile, response); + } catch (Exception e) { + log.error(">>> ${functionName}导出失败:", e); + CommonResponseUtil.renderError(response, "${functionName}导出失败"); + } finally { + FileUtil.del(tempFile); + } + } } diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl index 40c57b7c..00344ef7 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/Api.js.btl @@ -24,5 +24,21 @@ export default { // 获取${functionName}详情 ${classNameFirstLower}Detail(data) { return request('detail', data, 'get') - } + }, + // 下载${functionName}导入模板 + ${classNameFirstLower}DownloadTemplate(data) { + return request('downloadImportTemplate', data, 'get', { + responseType: 'blob' + }) + }, + // 导入${functionName} + ${classNameFirstLower}Import(data) { + return request('importData', data) + }, + // 导出${functionName} + ${classNameFirstLower}Export(data) { + return request('exportData', data, 'post', { + responseType: 'blob' + }) + } } diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl new file mode 100644 index 00000000..9d341f31 --- /dev/null +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/importModel.vue.btl @@ -0,0 +1,129 @@ + + + + diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl index 4ab5315e..c5b6de7e 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/frontend/index.vue.btl @@ -82,11 +82,7 @@ :data="loadData" :alert="options.alert.show" bordered - <% for(var i = 0; i < configList.~size; i++) { %> - <% if(configList[i].needTableId) { %> - :row-key="(record) => record.${configList[i].fieldNameCamelCase}" - <% } %> - <% } %> + :row-key="(record) => record.${dbTableKeyCamelCase}" :tool-config="toolConfig" :row-selection="options.rowSelection" > @@ -96,6 +92,14 @@ 新增 + + + 导入 + + + + 导出 + +
@@ -161,12 +166,15 @@ <% } %> import { cloneDeep } from 'lodash-es' import Form from './form.vue' + import ImportModel from './importModel.vue' + import downloadUtil from '@/utils/downloadUtil' import ${classNameFirstLower}Api from '@/api/${moduleName}/${classNameFirstLower}Api' <% if (searchCount > 0) { %> const searchFormState = ref({}) const searchFormRef = ref() <% } %> const tableRef = ref() + const importModelRef = ref() const formRef = ref() const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false } <% if(searchCount > 3) { %> @@ -245,17 +253,30 @@ const delete${className} = (record) => { let params = [ { - <% for(var i = 0; i < configList.~size; i++) { %> - <% if(configList[i].needTableId) { %> - ${configList[i].fieldNameCamelCase}: record.${configList[i].fieldNameCamelCase} - <% } %> - <% } %> + ${dbTableKeyCamelCase}: record.${dbTableKeyCamelCase} } ] ${classNameFirstLower}Api.${classNameFirstLower}Delete(params).then(() => { tableRef.value.refresh(true) }) } + // 导出 + const exportData = () => { + if (selectedRowKeys.value.length > 0) { + const params = selectedRowKeys.value.map((m) => { + return { + id: m + } + }) + ${classNameFirstLower}Api.${classNameFirstLower}Export(params).then((res) => { + downloadUtil.resultDownload(res) + }) + } else { + ${classNameFirstLower}Api.${classNameFirstLower}Export([]).then((res) => { + downloadUtil.resultDownload(res) + }) + } + } // 批量删除 const deleteBatch${className} = (params) => { ${classNameFirstLower}Api.${classNameFirstLower}Delete(params).then(() => { diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl index 1da419bc..5184a06f 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Mysql.sql.btl @@ -3,16 +3,19 @@ Date: ${genTime} */ -INSERT INTO `SYS_RESOURCE` VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('${importButtonId}', '${menuId}', '导入${functionName}', NULL, '${classNameFirstLower}Import', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); + +INSERT INTO `SYS_RESOURCE` VALUES ('${exportButtonId}', ${menuId}', '导出${functionName}', NULL, '${classNameFirstLower}Export', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); <% if (mobileModuleId != null && mobileModuleId != '') { %> INSERT INTO `MOBILE_RESOURCE` VALUES ('${menuId}', '0', '${functionName}管理', NULL, 'MENU', '${mobileModuleId}', 'MENU', '/pages/${moduleName}/${busName}/index', 'apartment-outlined', '#1890ff', 'YES', 'ENABLE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); diff --git a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl index 77d568d3..a4f5285a 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl +++ b/snowy-plugin/snowy-plugin-gen/src/main/resources/sqlend/Oracle.sql.btl @@ -3,16 +3,19 @@ Date: ${genTime} */ -INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, '99', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${menuId}', '${parentId}', '${functionName}管理', '${busName}', '${menuCode}', 'MENU', '${moduleId}', 'MENU', '${menuPath}', '${menuComponent}', NULL, NULL, NULL, NULL, NULL, '99', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '1', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${addButtonId}', '${menuId}', '新增${functionName}', NULL, '${classNameFirstLower}Add', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '1', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${batchDeleteButtonId}', '${menuId}', '批量删除${functionName}', NULL, '${classNameFirstLower}BatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '3', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${editButtonId}', '${menuId}', '编辑${functionName}', NULL, '${classNameFirstLower}Edit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '3', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '4', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${deleteButtonId}', '${menuId}', '删除${functionName}', NULL, '${classNameFirstLower}Delete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '4', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${importButtonId}', '${menuId}', '导入${functionName}', NULL, '${classNameFirstLower}Import', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '5', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); + +INSERT INTO "SNOWY"."SYS_RESOURCE" VALUES ('${exportButtonId}', '${menuId}', '导出${functionName}', NULL, '${classNameFirstLower}Export', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '6', NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); <% if (mobileModuleId != null && mobileModuleId != '') { %> INSERT INTO "SNOWY"."MOBILE_RESOURCE" VALUES ('${menuId}', '0', '${functionName}管理', NULL, 'MENU', '${mobileModuleId}', 'MENU', '/pages/${moduleName}/${busName}/index', 'apartment-outlined', '#1890ff', 'YES', 'ENABLE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java index 58a7eea4..d3714047 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java @@ -192,7 +192,7 @@ public class SysOrgServiceImpl extends ServiceImpl impleme this.removeByIds(toDeleteOrgIdList); // 发布删除事件 - CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.ORG.getValue(), toDeleteOrgIdList); + CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.ORG.getValue(), toDeleteOrgIdList); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java index 2059b746..503922ff 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java @@ -146,7 +146,7 @@ public class SysPositionServiceImpl extends ServiceImpl getUserIdListByRoleIdList(List roleIdList) { - return sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(roleIdList, + List userIdList = sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(roleIdList, SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue()); + if(ObjectUtil.isEmpty(userIdList)){ + return sysUserService.listByIds(userIdList).stream().map(SysUser::getId).collect(Collectors.toList()); + } else { + return CollectionUtil.newArrayList(); + } } @Override public List getUserIdListByGroupIdList(List groupIdList) { - return sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(groupIdList, + List userIdList = sysRelationService.getRelationObjectIdListByTargetIdListAndCategory(groupIdList, SysRelationCategoryEnum.SYS_USER_HAS_GROUP.getValue()); + if(ObjectUtil.isEmpty(userIdList)){ + return sysUserService.listByIds(userIdList).stream().map(SysUser::getId).collect(Collectors.toList()); + } else { + return CollectionUtil.newArrayList(); + } } @Override diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java index bccb9c75..fc091669 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java @@ -86,6 +86,14 @@ public class SysMenu extends CommonEntity { @Schema(description = "是否可见") private String visible; + /** 显示布局 */ + @Schema(description = "显示布局") + private String displayLayout; + + /** 缓存 */ + @Schema(description = "缓存") + private String keepLive; + /** 排序码 */ @Schema(description = "排序码") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java new file mode 100644 index 00000000..7f257067 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/enums/SysMenuWhetherEnum.java @@ -0,0 +1,37 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.resource.enums; + +import lombok.Getter; + +/** + * 菜单是否与 + * + * @author yubaoshan + * @date 2024/9/17 00:14 + **/ +@Getter +public enum SysMenuWhetherEnum { + + /** 写入 */ + YES("YES"), + + /** 不写入 */ + NO("NO"); + + private final String value; + + SysMenuWhetherEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java index 31d9a8ca..f569e1af 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java @@ -74,6 +74,14 @@ public class SysMenuAddParam { @Schema(description = "是否可见") private String visible; + /** 显示布局 */ + @Schema(description = "显示布局") + private String displayLayout; + + /** 缓存 */ + @Schema(description = "缓存") + private String keepLive; + /** 扩展信息 */ @Schema(description = "扩展信息") private String extJson; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java index 60256834..db4b43b0 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java @@ -79,6 +79,14 @@ public class SysMenuEditParam { @Schema(description = "是否可见") private String visible; + /** 显示布局 */ + @Schema(description = "显示布局") + private String displayLayout; + + /** 缓存 */ + @Schema(description = "缓存") + private String keepLive; + /** 扩展信息 */ @Schema(description = "扩展信息") private String extJson; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java index 476b9906..da092f92 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java @@ -115,7 +115,9 @@ public class SysButtonServiceImpl extends ServiceImpl { + JSONUtil.createObj().set("title", "批量删除").set("code", classNameFirstLower + "BatchDelete").set("sortCode", 4), + JSONUtil.createObj().set("title", "导入" + functionName).set("code", classNameFirstLower + "Import").set("sortCode", 5), + JSONUtil.createObj().set("title", "导出" + functionName).set("code", classNameFirstLower + "Export").set("sortCode", 6)).forEach(jsonObject -> { SysButtonAddParam sysButtonAddParam = new SysButtonAddParam(); BeanUtil.copyProperties(jsonObject, sysButtonAddParam); sysButtonAddParam.setParentId(sysMenu.getId()); @@ -171,7 +173,7 @@ public class SysButtonServiceImpl extends ServiceImpl impl this.removeByIds(toDeleteMenuIdList); // 发布删除事件 - CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.RESOURCE.getValue(), toDeleteMenuIdList); + CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.RESOURCE.getValue(), toDeleteMenuIdList); } } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java index afc4540a..b8cf9655 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java @@ -147,7 +147,7 @@ public class SysModuleServiceImpl extends ServiceImpl grantUser(@RequestBody @Valid SysRoleGrantUserParam sysRoleGrantUserParam) { + sysRoleGrantUserParam.setRemoveFirst(true); sysRoleService.grantUser(sysRoleGrantUserParam); return CommonResult.ok(); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java index 385823cf..24747824 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java @@ -39,4 +39,7 @@ public class SysRoleGrantUserParam { @Schema(description = "授权用户信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; + + /** 是否先清空授权信息 */ + private Boolean removeFirst = false; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java index a73be5a2..7c1b0dd4 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java @@ -233,7 +233,7 @@ public class SysRoleServiceImpl extends ServiceImpl impl this.removeByIds(sysRoleIdList); // 发布删除事件 - CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.ROLE.getValue(), sysRoleIdList); + CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.ROLE.getValue(), sysRoleIdList); } } @@ -326,8 +326,10 @@ public class SysRoleServiceImpl extends ServiceImpl impl public void grantUser(SysRoleGrantUserParam sysRoleGrantUserParam) { String id = sysRoleGrantUserParam.getId(); List grantInfoList = sysRoleGrantUserParam.getGrantInfoList(); - sysRelationService.remove(new LambdaQueryWrapper().eq(SysRelation::getTargetId, id) - .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue())); + if(sysRoleGrantUserParam.getRemoveFirst()) { + sysRelationService.remove(new LambdaQueryWrapper().eq(SysRelation::getTargetId, id) + .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue())); + } sysRelationService.saveBatch(grantInfoList.stream().map(userId -> { SysRelation sysRelation = new SysRelation(); sysRelation.setObjectId(userId); diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java index cb67619b..37af243e 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java @@ -41,9 +41,4 @@ public class SysUserBindEmailParam { @Schema(description = "验证码请求号") @NotBlank(message = "validCodeReqNo不能为空") private String validCodeReqNo; - - /** 新密码 */ - @Schema(description = "新密码") - @NotBlank(message = "newPassword不能为空") - private String newPassword; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java index 1c030601..ad3a6a82 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java @@ -65,6 +65,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.auth.core.util.StpLoginUserUtil; import vip.xiaonuo.common.cache.CommonCacheOperator; +import vip.xiaonuo.common.enums.CommonGenderEnum; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.excel.CommonExcelCustomMergeStrategy; import vip.xiaonuo.common.exception.CommonException; @@ -93,6 +94,7 @@ import vip.xiaonuo.sys.modular.relation.service.SysRelationService; import vip.xiaonuo.sys.modular.resource.entity.SysButton; import vip.xiaonuo.sys.modular.resource.entity.SysMenu; import vip.xiaonuo.sys.modular.resource.entity.SysModule; +import vip.xiaonuo.sys.modular.resource.enums.SysMenuWhetherEnum; import vip.xiaonuo.sys.modular.resource.enums.SysResourceCategoryEnum; import vip.xiaonuo.sys.modular.resource.enums.SysResourceMenuTypeEnum; import vip.xiaonuo.sys.modular.resource.service.SysButtonService; @@ -447,7 +449,7 @@ public class SysUserServiceImpl extends ServiceImpl impl sysUserExtService.remove(new LambdaQueryWrapper().in(SysUserExt::getUserId, sysUserIdList)); // 发布删除事件 - CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.USER.getValue(), sysUserIdList); + CommonDataChangeEventCenter.doDeleteWithDataIdList(SysDataTypeEnum.USER.getValue(), sysUserIdList); } } @@ -992,7 +994,7 @@ public class SysUserServiceImpl extends ServiceImpl impl // 执行校验验证码 validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo()); // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 - if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + if (ObjectUtil.isNotEmpty(this.getUserByEmail(email))) { throw new CommonException("邮箱:{}已存在对应用户", email); } // 生成邮箱验证码的值,随机6为数字 @@ -1034,7 +1036,7 @@ public class SysUserServiceImpl extends ServiceImpl impl // 执行校验验证码 validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo()); // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 - if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + if (ObjectUtil.isNotEmpty(this.getUserByEmail(email))) { throw new CommonException("邮箱:{}已存在对应用户", email); } // 生成邮箱验证码的值,随机6为数字 @@ -1074,7 +1076,7 @@ public class SysUserServiceImpl extends ServiceImpl impl throw new CommonException("邮箱:{}格式错误", email); } // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 - if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + if (ObjectUtil.isNotEmpty(this.getUserByEmail(email))) { throw new CommonException("邮箱:{}已存在对应用户", email); } // 执行校验验证码 @@ -1253,6 +1255,20 @@ public class SysUserServiceImpl extends ServiceImpl impl // 如果是首页,则设置affix metaJsonObject.set("affix", true); } + String menuMetaKeepLiveKey = "keepLive"; + String menuMetaDisplayLayoutKey = "displayLayout"; + // 设置缓存 + if (ObjectUtil.isEmpty(sysMenu.getKeepLive()) || sysMenu.getKeepLive().equals(SysMenuWhetherEnum.NO.getValue())) { + metaJsonObject.set(menuMetaKeepLiveKey, false); + } else if (sysMenu.getKeepLive().equals(SysMenuWhetherEnum.YES.getValue())) { + metaJsonObject.set(menuMetaKeepLiveKey, true); + } + // 设置显示布局 + if (ObjectUtil.isEmpty(sysMenu.getDisplayLayout()) || sysMenu.getDisplayLayout().equals(SysMenuWhetherEnum.YES.getValue())) { + metaJsonObject.set(menuMetaDisplayLayoutKey, true); + } else if (sysMenu.getDisplayLayout().equals(SysMenuWhetherEnum.NO.getValue())) { + metaJsonObject.set(menuMetaDisplayLayoutKey, false); + } } // 如果设置了不可见,那么设置为false,为了兼容已有,所以只是false的为不显示 if (ObjectUtil.isNotEmpty(sysMenu.getVisible()) && sysMenu.getVisible().equals("FALSE")) { @@ -1347,10 +1363,10 @@ public class SysUserServiceImpl extends ServiceImpl impl } } } - List extJsonList = sysUserGrantResourceParam.getGrantInfoList().stream() - .map(JSONUtil::toJsonStr).collect(Collectors.toList()); - sysRelationService.saveRelationBatchWithClear(sysUserGrantResourceParam.getId(), menuIdList, SysRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue(), extJsonList); } + List extJsonList = sysUserGrantResourceParam.getGrantInfoList().stream() + .map(JSONUtil::toJsonStr).collect(Collectors.toList()); + sysRelationService.saveRelationBatchWithClear(sysUserGrantResourceParam.getId(), menuIdList, SysRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue(), extJsonList); } @Override @@ -1551,7 +1567,7 @@ public class SysUserServiceImpl extends ServiceImpl impl FileUtil.FILE_SEPARATOR + "userImportTemplate.xlsx")); // 读取excel List sysUserImportParamList = EasyExcel.read(tempFile).head(SysUserImportParam.class).sheet() - .headRowNumber(2).doReadSync(); + .headRowNumber(3).doReadSync(); List allUserList = this.list(); for (int i = 0; i < sysUserImportParamList.size(); i++) { JSONObject jsonObject = this.doImport(allUserList, sysUserImportParamList.get(i), i); @@ -2147,6 +2163,7 @@ public class SysUserServiceImpl extends ServiceImpl impl sysUserAddParam.setPhone(phone); sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId()); sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId()); + sysUserAddParam.setGender(CommonGenderEnum.UNKNOWN.getValue()); // 保存用户 this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); // 获取用户信息 @@ -2182,6 +2199,7 @@ public class SysUserServiceImpl extends ServiceImpl impl sysUserAddParam.setEmail(email); sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId()); sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId()); + sysUserAddParam.setGender(CommonGenderEnum.UNKNOWN.getValue()); // 保存用户 this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); // 获取用户信息 @@ -2219,6 +2237,7 @@ public class SysUserServiceImpl extends ServiceImpl impl sysUserAddParam.setPassword(password); sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId()); sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId()); + sysUserAddParam.setGender(CommonGenderEnum.UNKNOWN.getValue()); // 保存用户 this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); // 获取用户信息 diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java index a2ccecd0..37b6ebe4 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java @@ -107,7 +107,7 @@ import java.util.Map; @MapperScan(basePackages = {"vip.xiaonuo.**.mapper"}) public class GlobalConfigure implements WebMvcConfigurer { - @Autowired + @Resource private SaTokenConfig saTokenConfig; private static final String COMMON_REPEAT_SUBMIT_CACHE_KEY = "common-repeatSubmit:"; @@ -118,7 +118,6 @@ public class GlobalConfigure implements WebMvcConfigurer { public static final String[] NO_LOGIN_PATH_ARR = { /* 主入口 */ "/", - /* 静态资源 */ "/favicon.ico", "/doc.html", @@ -133,11 +132,17 @@ public class GlobalConfigure implements WebMvcConfigurer { "/auth/c/getPhoneValidCode", "/auth/c/doLogin", "/auth/c/doLoginByPhone", + "/auth/c/register", + "/auth/c/getEmailValidCode", + "/auth/c/doLoginByEmail", "/auth/b/getPicCaptcha", "/auth/b/getPhoneValidCode", "/auth/b/doLogin", "/auth/b/doLoginByPhone", + "/auth/b/register", + "/auth/b/getEmailValidCode", + "/auth/b/doLoginByEmail", /* 三方登录相关 */ "/auth/third/render", @@ -154,7 +159,10 @@ public class GlobalConfigure implements WebMvcConfigurer { "/sys/userCenter/findPasswordGetPhoneValidCode", "/sys/userCenter/findPasswordGetEmailValidCode", "/sys/userCenter/findPasswordByPhone", - "/sys/userCenter/findPasswordByEmail" + "/sys/userCenter/findPasswordByEmail", + + /* 文件下载 */ + "/dev/file/download" }; /** diff --git a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql index 5d067fa4..da226a7b 100644 --- a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql +++ b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql @@ -587,6 +587,7 @@ CREATE TABLE `DEV_FILE` ( `OBJ_NAME` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件的对象名(唯一名称)', `STORAGE_PATH` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件存储路径', `DOWNLOAD_PATH` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件下载路径', + `IS_DOWNLOAD_AUTH` tinyint(1) NULL DEFAULT NULL COMMENT '文件下载是否需要授权', `THUMBNAIL` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '图片缩略图', `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', @@ -847,6 +848,7 @@ CREATE TABLE `GEN_CONFIG` ( `WHETHER_RETRACT` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '列省略', `WHETHER_ADD_UPDATE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否增改', `WHETHER_REQUIRED` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '必填', + `WHETHER_UNIQUE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '唯一', `QUERY_WHETHER` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '查询', `QUERY_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '查询方式', `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序', @@ -1196,6 +1198,8 @@ CREATE TABLE `SYS_RESOURCE` ( `ICON` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', `COLOR` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '颜色', `VISIBLE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否可见', + `DISPLAY_LAYOUT` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '显示布局', + `KEEP_LIVE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '页签缓存', `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序码', `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志',